aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgtags22
-rw-r--r--THIRD_PARTY_README2
-rw-r--r--bin/checkintest.sh266
-rw-r--r--bin/dump_octane_code.sh53
-rw-r--r--bin/fixorphantests.sh52
-rw-r--r--bin/fixwhitespace.sh17
-rw-r--r--bin/jjs.bat27
-rw-r--r--bin/jjssecure29
-rw-r--r--bin/jjssecure.bat27
-rw-r--r--bin/nashorn29
-rw-r--r--bin/nashorn.bat27
-rw-r--r--bin/nashornsecure29
-rw-r--r--bin/nashornsecure.bat27
-rw-r--r--bin/rm-non-tracked.sh24
-rw-r--r--bin/runopt.sh136
-rw-r--r--bin/verbose_octane.bat59
-rw-r--r--bin/verbose_octane.sh58
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java23
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java2
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java90
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java37
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java2
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java12
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java40
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java1
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java32
-rw-r--r--docs/DEVELOPER_README824
-rw-r--r--docs/genshelldoc.js10
-rw-r--r--docs/source/EvalFile.java10
-rw-r--r--docs/source/EvalScript.java10
-rw-r--r--docs/source/InvokeScriptFunction.java15
-rw-r--r--docs/source/InvokeScriptMethod.java17
-rw-r--r--docs/source/MultiScopes.java17
-rw-r--r--docs/source/RunnableImpl.java19
-rw-r--r--docs/source/RunnableImplObject.java21
-rw-r--r--docs/source/ScriptVars.java14
-rw-r--r--docs/source/importpackageclass.js12
-rw-r--r--docs/source/javaarray.js10
-rw-r--r--docs/source/javaextend.js10
-rw-r--r--docs/source/javaimporter.js10
-rw-r--r--docs/source/javatypes.js10
-rw-r--r--docs/source/overload.js12
-rw-r--r--docs/source/runnable.js10
-rw-r--r--docs/source/samfunc.js10
-rw-r--r--docs/source/test.js10
-rw-r--r--make/BuildNashorn.gmk2
-rw-r--r--make/build-benchmark.xml505
-rw-r--r--make/build-nasgen.xml8
-rw-r--r--make/build.xml207
-rw-r--r--make/nbproject/ide-targets.xml3
-rw-r--r--make/project.properties149
-rw-r--r--samples/BufferArray.java28
-rw-r--r--samples/array_mapreduce.js16
-rw-r--r--samples/astviewer.js12
-rw-r--r--samples/barchart_weather.js10
-rw-r--r--samples/browser_dom.js91
-rw-r--r--samples/call_lambda.js10
-rw-r--r--samples/counters.js10
-rw-r--r--samples/dirname.js10
-rw-r--r--samples/disassemble.js12
-rw-r--r--samples/engine/accessvar.js10
-rw-r--r--samples/engine/callfunc.js14
-rw-r--r--samples/engine/callmethod.js12
-rw-r--r--samples/engine/exposevar.js10
-rw-r--r--samples/engine/foreignobject.js12
-rw-r--r--samples/engine/hello.js10
-rw-r--r--samples/engine/interface.js12
-rw-r--r--samples/engine/interface2.js10
-rw-r--r--samples/engine/lambda_as_func.js10
-rw-r--r--samples/env.js14
-rw-r--r--samples/expression_closure.js10
-rw-r--r--samples/filebrowser.js10
-rw-r--r--samples/fileline.js10
-rw-r--r--samples/find_nonfinals2.js118
-rw-r--r--samples/fizzbuzz.js10
-rw-r--r--samples/for_each.js14
-rw-r--r--samples/gaussian_random.js12
-rw-r--r--samples/gaussian_random_bind.js12
-rw-r--r--samples/gutenberg.js12
-rw-r--r--samples/heredoc.js20
-rw-r--r--samples/interface_impl.js10
-rw-r--r--samples/javaastviewer.js16
-rw-r--r--samples/javacastcounter.js12
-rw-r--r--samples/javafoovars.js103
-rw-r--r--samples/javaimporter.js16
-rw-r--r--samples/javalist.js10
-rw-r--r--samples/javamap.js12
-rw-r--r--samples/javashell.js12
-rw-r--r--samples/jsadapter_dom.js14
-rw-r--r--samples/jsobj_example.js73
-rw-r--r--samples/jsobject.js10
-rw-r--r--samples/jsobject_mapreduce.js16
-rw-r--r--samples/jsonviewer.js14
-rw-r--r--samples/letter.js12
-rw-r--r--samples/list_mapreduce.js16
-rw-r--r--samples/locales.js10
-rw-r--r--samples/logisticmap.js10
-rw-r--r--samples/options.js10
-rw-r--r--samples/parser.js10
-rw-r--r--samples/readLine.js10
-rw-r--r--samples/sam_function.js12
-rw-r--r--samples/shell.js10
-rw-r--r--samples/stack.js18
-rw-r--r--samples/uniform_random.js10
-rw-r--r--samples/uniq.js10
-rw-r--r--samples/uniqs.js12
-rw-r--r--samples/weather.js10
-rw-r--r--samples/word_histogram.js10
-rw-r--r--samples/zipfs.js48
-rw-r--r--samples/ziplist.js80
-rw-r--r--src/jdk/internal/dynalink/ChainedCallSite.java74
-rw-r--r--src/jdk/internal/dynalink/DefaultBootstrapper.java6
-rw-r--r--src/jdk/internal/dynalink/DynamicLinker.java26
-rw-r--r--src/jdk/internal/dynalink/DynamicLinkerFactory.java84
-rw-r--r--src/jdk/internal/dynalink/GuardedInvocationFilter.java105
-rw-r--r--src/jdk/internal/dynalink/MonomorphicCallSite.java6
-rw-r--r--src/jdk/internal/dynalink/NoSuchDynamicMethodException.java2
-rw-r--r--src/jdk/internal/dynalink/beans/AbstractJavaLinker.java250
-rw-r--r--src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java10
-rw-r--r--src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java8
-rw-r--r--src/jdk/internal/dynalink/beans/BeanIntrospector.java4
-rw-r--r--src/jdk/internal/dynalink/beans/BeanLinker.java52
-rw-r--r--src/jdk/internal/dynalink/beans/BeansLinker.java44
-rw-r--r--src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java10
-rw-r--r--src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java13
-rw-r--r--src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java4
-rw-r--r--src/jdk/internal/dynalink/beans/ClassString.java14
-rw-r--r--src/jdk/internal/dynalink/beans/DynamicMethod.java13
-rw-r--r--src/jdk/internal/dynalink/beans/DynamicMethodLinker.java27
-rw-r--r--src/jdk/internal/dynalink/beans/FacetIntrospector.java10
-rw-r--r--src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java30
-rw-r--r--src/jdk/internal/dynalink/beans/MaximallySpecific.java30
-rw-r--r--src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java40
-rw-r--r--src/jdk/internal/dynalink/beans/OverloadedMethod.java42
-rw-r--r--src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java26
-rw-r--r--src/jdk/internal/dynalink/beans/SingleDynamicMethod.java26
-rw-r--r--src/jdk/internal/dynalink/beans/StaticClass.java6
-rw-r--r--src/jdk/internal/dynalink/beans/StaticClassIntrospector.java10
-rw-r--r--src/jdk/internal/dynalink/beans/StaticClassLinker.java29
-rw-r--r--src/jdk/internal/dynalink/linker/GuardedInvocation.java188
-rw-r--r--src/jdk/internal/dynalink/linker/GuardedTypeConversion.java16
-rw-r--r--src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java14
-rw-r--r--src/jdk/internal/dynalink/linker/LinkRequest.java22
-rw-r--r--src/jdk/internal/dynalink/linker/LinkerServices.java47
-rw-r--r--src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java100
-rw-r--r--src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java8
-rw-r--r--src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java4
-rw-r--r--src/jdk/internal/dynalink/support/AutoDiscovery.java4
-rw-r--r--src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java4
-rw-r--r--src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java36
-rw-r--r--src/jdk/internal/dynalink/support/ClassMap.java2
-rw-r--r--src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java6
-rw-r--r--src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java26
-rw-r--r--src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java8
-rw-r--r--src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java99
-rw-r--r--src/jdk/internal/dynalink/support/Guards.java42
-rw-r--r--src/jdk/internal/dynalink/support/LinkRequestImpl.java22
-rw-r--r--src/jdk/internal/dynalink/support/LinkerServicesImpl.java17
-rw-r--r--src/jdk/internal/dynalink/support/Lookup.java56
-rw-r--r--src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java6
-rw-r--r--src/jdk/internal/dynalink/support/NameCodec.java10
-rw-r--r--src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java6
-rw-r--r--src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java14
-rw-r--r--src/jdk/internal/dynalink/support/TypeConverterFactory.java83
-rw-r--r--src/jdk/internal/dynalink/support/TypeUtilities.java212
-rw-r--r--src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java6
-rw-r--r--src/jdk/internal/dynalink/support/messages.properties2
-rw-r--r--src/jdk/nashorn/api/scripting/ClassFilter.java41
-rw-r--r--src/jdk/nashorn/api/scripting/Formatter.java6
-rw-r--r--src/jdk/nashorn/api/scripting/JSObject.java1
-rw-r--r--src/jdk/nashorn/api/scripting/NashornException.java17
-rw-r--r--src/jdk/nashorn/api/scripting/NashornScriptEngine.java165
-rw-r--r--src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java74
-rw-r--r--src/jdk/nashorn/api/scripting/ScriptObjectMirror.java38
-rw-r--r--src/jdk/nashorn/api/scripting/ScriptUtils.java21
-rw-r--r--src/jdk/nashorn/api/scripting/URLReader.java2
-rw-r--r--src/jdk/nashorn/api/scripting/resources/engine.js101
-rw-r--r--src/jdk/nashorn/internal/AssertsEnabled.java45
-rw-r--r--src/jdk/nashorn/internal/IntDeque.java87
-rw-r--r--src/jdk/nashorn/internal/codegen/ApplySpecialization.java397
-rw-r--r--src/jdk/nashorn/internal/codegen/AssignSymbols.java1072
-rw-r--r--src/jdk/nashorn/internal/codegen/AstSerializer.java73
-rw-r--r--src/jdk/nashorn/internal/codegen/Attr.java1947
-rw-r--r--src/jdk/nashorn/internal/codegen/BranchOptimizer.java93
-rw-r--r--src/jdk/nashorn/internal/codegen/ClassEmitter.java196
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGenerator.java4949
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java166
-rw-r--r--src/jdk/nashorn/internal/codegen/CompilationPhase.java886
-rw-r--r--src/jdk/nashorn/internal/codegen/CompileUnit.java88
-rw-r--r--src/jdk/nashorn/internal/codegen/Compiler.java990
-rw-r--r--src/jdk/nashorn/internal/codegen/CompilerConstants.java152
-rw-r--r--src/jdk/nashorn/internal/codegen/Condition.java6
-rw-r--r--src/jdk/nashorn/internal/codegen/ConstantData.java28
-rw-r--r--src/jdk/nashorn/internal/codegen/DumpBytecode.java120
-rw-r--r--src/jdk/nashorn/internal/codegen/FieldObjectCreator.java129
-rw-r--r--src/jdk/nashorn/internal/codegen/FinalizeTypes.java199
-rw-r--r--src/jdk/nashorn/internal/codegen/FindScopeDepths.java368
-rw-r--r--src/jdk/nashorn/internal/codegen/FoldConstants.java80
-rw-r--r--src/jdk/nashorn/internal/codegen/FunctionSignature.java10
-rw-r--r--src/jdk/nashorn/internal/codegen/Label.java524
-rw-r--r--src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java59
-rw-r--r--src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java1562
-rw-r--r--src/jdk/nashorn/internal/codegen/Lower.java224
-rw-r--r--src/jdk/nashorn/internal/codegen/MapCreator.java92
-rw-r--r--src/jdk/nashorn/internal/codegen/MapTuple.java66
-rw-r--r--src/jdk/nashorn/internal/codegen/MethodEmitter.java963
-rw-r--r--src/jdk/nashorn/internal/codegen/Namespace.java1
-rw-r--r--src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java603
-rw-r--r--src/jdk/nashorn/internal/codegen/ObjectCreator.java54
-rw-r--r--src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java257
-rw-r--r--src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java549
-rw-r--r--src/jdk/nashorn/internal/codegen/ProgramPoints.java132
-rw-r--r--src/jdk/nashorn/internal/codegen/RangeAnalyzer.java475
-rw-r--r--src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java85
-rw-r--r--src/jdk/nashorn/internal/codegen/RuntimeCallSite.java36
-rw-r--r--src/jdk/nashorn/internal/codegen/SharedScopeCall.java28
-rw-r--r--src/jdk/nashorn/internal/codegen/SpillObjectCreator.java179
-rw-r--r--src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java446
-rw-r--r--src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java100
-rw-r--r--src/jdk/nashorn/internal/codegen/Splitter.java30
-rw-r--r--src/jdk/nashorn/internal/codegen/TypeEvaluator.java250
-rw-r--r--src/jdk/nashorn/internal/codegen/TypeMap.java166
-rw-r--r--src/jdk/nashorn/internal/codegen/WeighNodes.java52
-rw-r--r--src/jdk/nashorn/internal/codegen/anchor.properties (renamed from bin/jjs)6
-rw-r--r--src/jdk/nashorn/internal/codegen/types/ArrayType.java1
-rw-r--r--src/jdk/nashorn/internal/codegen/types/BitwiseType.java1
-rw-r--r--src/jdk/nashorn/internal/codegen/types/BooleanType.java53
-rw-r--r--src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java25
-rw-r--r--src/jdk/nashorn/internal/codegen/types/BytecodeOps.java14
-rw-r--r--src/jdk/nashorn/internal/codegen/types/IntType.java141
-rw-r--r--src/jdk/nashorn/internal/codegen/types/LongType.java69
-rw-r--r--src/jdk/nashorn/internal/codegen/types/NumberType.java40
-rw-r--r--src/jdk/nashorn/internal/codegen/types/NumericType.java2
-rw-r--r--src/jdk/nashorn/internal/codegen/types/ObjectType.java49
-rw-r--r--src/jdk/nashorn/internal/codegen/types/Range.java705
-rw-r--r--src/jdk/nashorn/internal/codegen/types/Type.java370
-rw-r--r--src/jdk/nashorn/internal/ir/AccessNode.java66
-rw-r--r--src/jdk/nashorn/internal/ir/BaseNode.java54
-rw-r--r--src/jdk/nashorn/internal/ir/BinaryNode.java336
-rw-r--r--src/jdk/nashorn/internal/ir/Block.java126
-rw-r--r--src/jdk/nashorn/internal/ir/BlockLexicalContext.java16
-rw-r--r--src/jdk/nashorn/internal/ir/BlockStatement.java10
-rw-r--r--src/jdk/nashorn/internal/ir/BreakNode.java48
-rw-r--r--src/jdk/nashorn/internal/ir/BreakableNode.java10
-rw-r--r--src/jdk/nashorn/internal/ir/BreakableStatement.java25
-rw-r--r--src/jdk/nashorn/internal/ir/CallNode.java195
-rw-r--r--src/jdk/nashorn/internal/ir/CaseNode.java46
-rw-r--r--src/jdk/nashorn/internal/ir/CatchNode.java36
-rw-r--r--src/jdk/nashorn/internal/ir/CompileUnitHolder.java40
-rw-r--r--src/jdk/nashorn/internal/ir/ContinueNode.java46
-rw-r--r--src/jdk/nashorn/internal/ir/EmptyNode.java3
-rw-r--r--src/jdk/nashorn/internal/ir/Expression.java147
-rw-r--r--src/jdk/nashorn/internal/ir/ExpressionStatement.java11
-rw-r--r--src/jdk/nashorn/internal/ir/Flags.java6
-rw-r--r--src/jdk/nashorn/internal/ir/ForNode.java103
-rw-r--r--src/jdk/nashorn/internal/ir/FunctionCall.java14
-rw-r--r--src/jdk/nashorn/internal/ir/FunctionNode.java818
-rw-r--r--src/jdk/nashorn/internal/ir/GetSplitState.java70
-rw-r--r--src/jdk/nashorn/internal/ir/IdentNode.java237
-rw-r--r--src/jdk/nashorn/internal/ir/IfNode.java37
-rw-r--r--src/jdk/nashorn/internal/ir/IndexNode.java43
-rw-r--r--src/jdk/nashorn/internal/ir/JoinPredecessor.java49
-rw-r--r--src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java132
-rw-r--r--src/jdk/nashorn/internal/ir/JumpStatement.java120
-rw-r--r--src/jdk/nashorn/internal/ir/LabelNode.java56
-rw-r--r--src/jdk/nashorn/internal/ir/Labels.java (renamed from src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java)32
-rw-r--r--src/jdk/nashorn/internal/ir/LexicalContext.java151
-rw-r--r--src/jdk/nashorn/internal/ir/LexicalContextExpression.java18
-rw-r--r--src/jdk/nashorn/internal/ir/LexicalContextStatement.java2
-rw-r--r--src/jdk/nashorn/internal/ir/LiteralNode.java399
-rw-r--r--src/jdk/nashorn/internal/ir/LocalVariableConversion.java174
-rw-r--r--src/jdk/nashorn/internal/ir/LoopNode.java29
-rw-r--r--src/jdk/nashorn/internal/ir/Node.java123
-rw-r--r--src/jdk/nashorn/internal/ir/ObjectNode.java14
-rw-r--r--src/jdk/nashorn/internal/ir/Optimistic.java92
-rw-r--r--src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java128
-rw-r--r--src/jdk/nashorn/internal/ir/PropertyNode.java11
-rw-r--r--src/jdk/nashorn/internal/ir/ReturnNode.java6
-rw-r--r--src/jdk/nashorn/internal/ir/RuntimeNode.java133
-rw-r--r--src/jdk/nashorn/internal/ir/SetSplitState.java70
-rw-r--r--src/jdk/nashorn/internal/ir/SplitNode.java48
-rw-r--r--src/jdk/nashorn/internal/ir/SplitReturn.java64
-rw-r--r--src/jdk/nashorn/internal/ir/Statement.java31
-rw-r--r--src/jdk/nashorn/internal/ir/SwitchNode.java62
-rw-r--r--src/jdk/nashorn/internal/ir/Symbol.java617
-rw-r--r--src/jdk/nashorn/internal/ir/TemporarySymbols.java169
-rw-r--r--src/jdk/nashorn/internal/ir/Terminal.java37
-rw-r--r--src/jdk/nashorn/internal/ir/TernaryNode.java55
-rw-r--r--src/jdk/nashorn/internal/ir/ThrowNode.java46
-rw-r--r--src/jdk/nashorn/internal/ir/TryNode.java59
-rw-r--r--src/jdk/nashorn/internal/ir/UnaryNode.java217
-rw-r--r--src/jdk/nashorn/internal/ir/VarNode.java80
-rw-r--r--src/jdk/nashorn/internal/ir/WhileNode.java42
-rw-r--r--src/jdk/nashorn/internal/ir/WithNode.java6
-rw-r--r--src/jdk/nashorn/internal/ir/debug/ASTWriter.java29
-rw-r--r--src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java2
-rw-r--r--src/jdk/nashorn/internal/ir/debug/JSONWriter.java81
-rw-r--r--src/jdk/nashorn/internal/ir/debug/NashornClassReader.java551
-rw-r--r--src/jdk/nashorn/internal/ir/debug/NashornTextifier.java1257
-rw-r--r--src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java10
-rw-r--r--src/jdk/nashorn/internal/ir/debug/PrintVisitor.java126
-rw-r--r--src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java24
-rw-r--r--src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java85
-rw-r--r--src/jdk/nashorn/internal/lookup/Lookup.java56
-rw-r--r--src/jdk/nashorn/internal/lookup/MethodHandleFactory.java438
-rw-r--r--src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java34
-rw-r--r--src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/ArrayBufferView.java440
-rw-r--r--src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java2
-rw-r--r--src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/Global.java654
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArray.java805
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArrayBuffer.java166
-rw-r--r--src/jdk/nashorn/internal/objects/NativeBoolean.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDataView.java235
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDate.java10
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDebug.java207
-rw-r--r--src/jdk/nashorn/internal/objects/NativeError.java45
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat32Array.java131
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat64Array.java141
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFunction.java101
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt16Array.java134
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt32Array.java137
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt8Array.java126
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJSAdapter.java173
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJSON.java4
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJava.java77
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJavaImporter.java37
-rw-r--r--src/jdk/nashorn/internal/objects/NativeMath.java28
-rw-r--r--src/jdk/nashorn/internal/objects/NativeNumber.java78
-rw-r--r--src/jdk/nashorn/internal/objects/NativeObject.java83
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExp.java88
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java4
-rw-r--r--src/jdk/nashorn/internal/objects/NativeStrictArguments.java7
-rw-r--r--src/jdk/nashorn/internal/objects/NativeString.java325
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint16Array.java139
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint32Array.java142
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8Array.java133
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java183
-rw-r--r--src/jdk/nashorn/internal/objects/PrototypeObject.java2
-rw-r--r--src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java65
-rw-r--r--src/jdk/nashorn/internal/objects/annotations/Optimistic.java (renamed from src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java)33
-rw-r--r--src/jdk/nashorn/internal/objects/annotations/Property.java4
-rw-r--r--src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java186
-rw-r--r--src/jdk/nashorn/internal/parser/AbstractParser.java66
-rw-r--r--src/jdk/nashorn/internal/parser/JSONParser.java5
-rw-r--r--src/jdk/nashorn/internal/parser/Lexer.java64
-rw-r--r--src/jdk/nashorn/internal/parser/Parser.java710
-rw-r--r--src/jdk/nashorn/internal/parser/Token.java22
-rw-r--r--src/jdk/nashorn/internal/parser/TokenStream.java4
-rw-r--r--src/jdk/nashorn/internal/parser/TokenType.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/AccessorProperty.java724
-rw-r--r--src/jdk/nashorn/internal/runtime/AllocationStrategy.java104
-rw-r--r--src/jdk/nashorn/internal/runtime/AstDeserializer.java47
-rw-r--r--src/jdk/nashorn/internal/runtime/CodeInstaller.java51
-rw-r--r--src/jdk/nashorn/internal/runtime/CodeStore.java356
-rw-r--r--src/jdk/nashorn/internal/runtime/CompiledFunction.java955
-rw-r--r--src/jdk/nashorn/internal/runtime/CompiledFunctions.java114
-rw-r--r--src/jdk/nashorn/internal/runtime/ConsString.java46
-rw-r--r--src/jdk/nashorn/internal/runtime/Context.java555
-rw-r--r--src/jdk/nashorn/internal/runtime/Debug.java37
-rw-r--r--src/jdk/nashorn/internal/runtime/DebugLogger.java304
-rw-r--r--src/jdk/nashorn/internal/runtime/DebuggerSupport.java8
-rw-r--r--src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java104
-rw-r--r--src/jdk/nashorn/internal/runtime/ECMAErrors.java15
-rw-r--r--src/jdk/nashorn/internal/runtime/ECMAException.java24
-rw-r--r--src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java82
-rw-r--r--src/jdk/nashorn/internal/runtime/FindProperty.java133
-rw-r--r--src/jdk/nashorn/internal/runtime/FunctionInitializer.java160
-rw-r--r--src/jdk/nashorn/internal/runtime/FunctionScope.java13
-rw-r--r--src/jdk/nashorn/internal/runtime/GlobalConstants.java486
-rw-r--r--src/jdk/nashorn/internal/runtime/GlobalFunctions.java82
-rw-r--r--src/jdk/nashorn/internal/runtime/JSONFunctions.java18
-rw-r--r--src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/JSType.java946
-rw-r--r--src/jdk/nashorn/internal/runtime/ListAdapter.java13
-rw-r--r--src/jdk/nashorn/internal/runtime/Logging.java178
-rw-r--r--src/jdk/nashorn/internal/runtime/NashornLoader.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/NativeJavaPackage.java47
-rw-r--r--src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java65
-rw-r--r--src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java291
-rw-r--r--src/jdk/nashorn/internal/runtime/Property.java336
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyAccess.java100
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyDescriptor.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyHashMap.java85
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyListeners.java23
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyMap.java321
-rw-r--r--src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java983
-rw-r--r--src/jdk/nashorn/internal/runtime/RewriteException.java420
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptEnvironment.java117
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptFunction.java518
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptFunctionData.java456
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptLoader.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptObject.java1741
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptRuntime.java259
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptingFunctions.java36
-rw-r--r--src/jdk/nashorn/internal/runtime/SetMethodCreator.java145
-rw-r--r--src/jdk/nashorn/internal/runtime/Source.java206
-rw-r--r--src/jdk/nashorn/internal/runtime/Specialization.java114
-rw-r--r--src/jdk/nashorn/internal/runtime/SpillProperty.java217
-rw-r--r--src/jdk/nashorn/internal/runtime/StoredScript.java (renamed from src/jdk/nashorn/internal/runtime/CompiledScript.java)61
-rw-r--r--src/jdk/nashorn/internal/runtime/Timing.java250
-rw-r--r--src/jdk/nashorn/internal/runtime/Undefined.java55
-rw-r--r--src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java167
-rw-r--r--src/jdk/nashorn/internal/runtime/UserAccessorProperty.java368
-rw-r--r--src/jdk/nashorn/internal/runtime/WithObject.java113
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/AnyElements.java38
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayData.java514
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java31
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java8
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java36
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java364
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java10
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java31
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java15
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java246
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/IntElements.java34
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java34
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java198
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java214
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java186
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java68
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java195
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/NumericElements.java35
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java173
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java88
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java204
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java34
-rw-r--r--src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java67
-rw-r--r--src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java87
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/Bootstrap.java211
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/BoundCallable.java96
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java132
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java91
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java225
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/InvokeByName.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java107
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java262
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java25
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java10
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java47
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java28
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java81
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java120
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java25
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java147
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornGuards.java100
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornLinker.java20
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java11
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java6
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java44
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/logging/DebugLogger.java606
-rw-r--r--src/jdk/nashorn/internal/runtime/logging/Loggable.java56
-rw-r--r--src/jdk/nashorn/internal/runtime/logging/Logger.java48
-rw-r--r--src/jdk/nashorn/internal/runtime/options/KeyValueOption.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/options/LoggingOption.java133
-rw-r--r--src/jdk/nashorn/internal/runtime/options/Options.java50
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/RegExp.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java466
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java216
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java68
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java14
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java395
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java36
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java210
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java38
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Config.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java67
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java277
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java263
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java76
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java25
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java62
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java73
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java48
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Option.java81
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java175
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java72
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Region.java9
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java17
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java44
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java151
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java34
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java217
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Token.java20
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java83
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java169
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java39
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java15
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java48
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java83
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java33
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java1
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Messages.properties23
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Options.properties93
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js4
-rw-r--r--src/jdk/nashorn/internal/scripts/JO.java13
-rw-r--r--src/jdk/nashorn/tools/Shell.java31
-rw-r--r--test/examples/apply_to_call_benchmark.js68
-rw-r--r--test/examples/array-micro.js10
-rw-r--r--test/examples/charcodeat-benchmark.js (renamed from test/script/basic/ranges_payload.js)77
-rw-r--r--test/examples/dual-fields-micro.js16
-rw-r--r--test/examples/getter-setter-micro.js81
-rw-r--r--test/examples/innerbench.js10
-rw-r--r--test/examples/int-micro.js10
-rw-r--r--test/examples/push-pop-benchmark.js59
-rw-r--r--test/examples/string-micro.js18
-rw-r--r--test/examples/typechain.js10
-rw-r--r--test/lib/benchmark.js18
-rw-r--r--test/opt/add.js12
-rw-r--r--test/opt/add_constant.js12
-rw-r--r--test/opt/add_reuse_callsite.js14
-rw-r--r--test/opt/add_revert2.js14
-rw-r--r--test/opt/cascade_specialize.js10
-rw-r--r--test/script/assert.js18
-rw-r--r--test/script/basic/8024180/global_var_delete.js8
-rw-r--r--test/script/basic/8024180/global_var_shadow.js8
-rw-r--r--test/script/basic/8024180/scope_no_such_prop.js8
-rw-r--r--test/script/basic/8024180/with_expr_prop_add.js8
-rw-r--r--test/script/basic/8024180/with_expr_proto_prop_add.js10
-rw-r--r--test/script/basic/8024180/with_java_object.js8
-rw-r--r--test/script/basic/JDK-8005958.js10
-rw-r--r--test/script/basic/JDK-8006304.js10
-rw-r--r--test/script/basic/JDK-8006337.js10
-rw-r--r--test/script/basic/JDK-8006529-b.js10
-rw-r--r--test/script/basic/JDK-8006570.js10
-rw-r--r--test/script/basic/JDK-8006852a.js48
-rw-r--r--test/script/basic/JDK-8006852b.js10
-rw-r--r--test/script/basic/JDK-8006857.js8
-rw-r--r--test/script/basic/JDK-8006983.js8
-rw-r--r--test/script/basic/JDK-8006984.js28
-rw-r--r--test/script/basic/JDK-8007060.js2
-rw-r--r--test/script/basic/JDK-8007140.js8
-rw-r--r--test/script/basic/JDK-8007215.js16
-rw-r--r--test/script/basic/JDK-8007460.js10
-rw-r--r--test/script/basic/JDK-8007522.js8
-rw-r--r--test/script/basic/JDK-8007523.js10
-rw-r--r--test/script/basic/JDK-8007619.js12
-rw-r--r--test/script/basic/JDK-8007990.js8
-rw-r--r--test/script/basic/JDK-8008197.js10
-rw-r--r--test/script/basic/JDK-8008206.js18
-rw-r--r--test/script/basic/JDK-8008238.js8
-rw-r--r--test/script/basic/JDK-8008554.js8
-rw-r--r--test/script/basic/JDK-8008814-3.js8
-rw-r--r--test/script/basic/JDK-8008814-4.js8
-rw-r--r--test/script/basic/JDK-8009553.js8
-rw-r--r--test/script/basic/JDK-8009868.js8
-rw-r--r--test/script/basic/JDK-8010709.js2
-rw-r--r--test/script/basic/JDK-8010710.js20
-rw-r--r--test/script/basic/JDK-8010720.js8
-rw-r--r--test/script/basic/JDK-8010731.js64
-rw-r--r--test/script/basic/JDK-8010804.js10
-rw-r--r--test/script/basic/JDK-8010946-privileged.js2
-rw-r--r--test/script/basic/JDK-8010946.js2
-rw-r--r--test/script/basic/JDK-8011023.js10
-rw-r--r--test/script/basic/JDK-8011209.js8
-rw-r--r--test/script/basic/JDK-8011237.js8
-rw-r--r--test/script/basic/JDK-8011274.js8
-rw-r--r--test/script/basic/JDK-8011357.js8
-rw-r--r--test/script/basic/JDK-8011362.js8
-rw-r--r--test/script/basic/JDK-8011365.js12
-rw-r--r--test/script/basic/JDK-8011382.js10
-rw-r--r--test/script/basic/JDK-8011394.js8
-rw-r--r--test/script/basic/JDK-8011552.js8
-rw-r--r--test/script/basic/JDK-8011555.js10
-rw-r--r--test/script/basic/JDK-8011578.js8
-rw-r--r--test/script/basic/JDK-8011718.js26
-rw-r--r--test/script/basic/JDK-8011756.js8
-rw-r--r--test/script/basic/JDK-8011893.js8
-rw-r--r--test/script/basic/JDK-8011960.js8
-rw-r--r--test/script/basic/JDK-8011964.js8
-rw-r--r--test/script/basic/JDK-8011974.js8
-rw-r--r--test/script/basic/JDK-8012083.js10
-rw-r--r--test/script/basic/JDK-8012164.js12
-rw-r--r--test/script/basic/JDK-8012191.js10
-rw-r--r--test/script/basic/JDK-8012240.js14
-rw-r--r--test/script/basic/JDK-8012291.js8
-rw-r--r--test/script/basic/JDK-8012305.js4
-rw-r--r--test/script/basic/JDK-8012457.js10
-rw-r--r--test/script/basic/JDK-8012462.js8
-rw-r--r--test/script/basic/JDK-8013131.js8
-rw-r--r--test/script/basic/JDK-8013167.js10
-rw-r--r--test/script/basic/JDK-8013325.js12
-rw-r--r--test/script/basic/JDK-8013337.js4
-rw-r--r--test/script/basic/JDK-8013444.js12
-rw-r--r--test/script/basic/JDK-8013729.js8
-rw-r--r--test/script/basic/JDK-8013873.js8
-rw-r--r--test/script/basic/JDK-8013874.js8
-rw-r--r--test/script/basic/JDK-8013878.js8
-rw-r--r--test/script/basic/JDK-8013919.js10
-rw-r--r--test/script/basic/JDK-8014426.js8
-rw-r--r--test/script/basic/JDK-8014647.js8
-rw-r--r--test/script/basic/JDK-8014781.js8
-rw-r--r--test/script/basic/JDK-8014785.js10
-rw-r--r--test/script/basic/JDK-8014953.js10
-rw-r--r--test/script/basic/JDK-8015267.js18
-rw-r--r--test/script/basic/JDK-8015345.js8
-rw-r--r--test/script/basic/JDK-8015346.js8
-rw-r--r--test/script/basic/JDK-8015347.js8
-rw-r--r--test/script/basic/JDK-8015348.js8
-rw-r--r--test/script/basic/JDK-8015349.js10
-rw-r--r--test/script/basic/JDK-8015350.js8
-rw-r--r--test/script/basic/JDK-8015352.js8
-rw-r--r--test/script/basic/JDK-8015353.js8
-rw-r--r--test/script/basic/JDK-8015354.js2
-rw-r--r--test/script/basic/JDK-8015355.js10
-rw-r--r--test/script/basic/JDK-8015356.js10
-rw-r--r--test/script/basic/JDK-8015357.js12
-rw-r--r--test/script/basic/JDK-8015741.js8
-rw-r--r--test/script/basic/JDK-8015830.js8
-rw-r--r--test/script/basic/JDK-8015892.js22
-rw-r--r--test/script/basic/JDK-8015945.js8
-rw-r--r--test/script/basic/JDK-8015959.js8
-rw-r--r--test/script/basic/JDK-8015969.js35
-rw-r--r--test/script/basic/JDK-8016235.js24
-rw-r--r--test/script/basic/JDK-8016239.js8
-rw-r--r--test/script/basic/JDK-8016518.js8
-rw-r--r--test/script/basic/JDK-8016542.js8
-rw-r--r--test/script/basic/JDK-8016618.js24
-rw-r--r--test/script/basic/JDK-8016618.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8016667.js16
-rw-r--r--test/script/basic/JDK-8016681.js8
-rw-r--r--test/script/basic/JDK-8017046.js8
-rw-r--r--test/script/basic/JDK-8017082.js8
-rw-r--r--test/script/basic/JDK-8017084.js8
-rw-r--r--test/script/basic/JDK-8017768.js2
-rw-r--r--test/script/basic/JDK-8017950.js10
-rw-r--r--test/script/basic/JDK-8019226.js10
-rw-r--r--test/script/basic/JDK-8019473.js8
-rw-r--r--test/script/basic/JDK-8019478.js8
-rw-r--r--test/script/basic/JDK-8019482.js8
-rw-r--r--test/script/basic/JDK-8019488.js8
-rw-r--r--test/script/basic/JDK-8019508.js8
-rw-r--r--test/script/basic/JDK-8019553.js8
-rw-r--r--test/script/basic/JDK-8019585.js10
-rw-r--r--test/script/basic/JDK-8019629.js10
-rw-r--r--test/script/basic/JDK-8019783.js8
-rw-r--r--test/script/basic/JDK-8019791.js8
-rw-r--r--test/script/basic/JDK-8019805.js8
-rw-r--r--test/script/basic/JDK-8019808.js10
-rw-r--r--test/script/basic/JDK-8019809.js10
-rw-r--r--test/script/basic/JDK-8019810.js8
-rw-r--r--test/script/basic/JDK-8019811.js20
-rw-r--r--test/script/basic/JDK-8019814.js20
-rw-r--r--test/script/basic/JDK-8019817.js10
-rw-r--r--test/script/basic/JDK-8019819.js10
-rw-r--r--test/script/basic/JDK-8019821.js18
-rw-r--r--test/script/basic/JDK-8019822.js8
-rw-r--r--test/script/basic/JDK-8019947.js8
-rw-r--r--test/script/basic/JDK-8019963.js8
-rw-r--r--test/script/basic/JDK-8019983.js20
-rw-r--r--test/script/basic/JDK-8019985.js8
-rw-r--r--test/script/basic/JDK-8020124.js8
-rw-r--r--test/script/basic/JDK-8020132.js8
-rw-r--r--test/script/basic/JDK-8020223.js8
-rw-r--r--test/script/basic/JDK-8020324.js8
-rw-r--r--test/script/basic/JDK-8020325.js8
-rw-r--r--test/script/basic/JDK-8020354.js8
-rw-r--r--test/script/basic/JDK-8020355.js8
-rw-r--r--test/script/basic/JDK-8020356.js8
-rw-r--r--test/script/basic/JDK-8020357.js10
-rw-r--r--test/script/basic/JDK-8020358.js8
-rw-r--r--test/script/basic/JDK-8020380.js8
-rw-r--r--test/script/basic/JDK-8020437.js8
-rw-r--r--test/script/basic/JDK-8020463.js8
-rw-r--r--test/script/basic/JDK-8020508.js10
-rw-r--r--test/script/basic/JDK-8021122.js8
-rw-r--r--test/script/basic/JDK-8022598.js8
-rw-r--r--test/script/basic/JDK-8022731.js8
-rw-r--r--test/script/basic/JDK-8022903.js10
-rw-r--r--test/script/basic/JDK-8022903.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8023026.js8
-rw-r--r--test/script/basic/JDK-8023373.js10
-rw-r--r--test/script/basic/JDK-8023531.js8
-rw-r--r--test/script/basic/JDK-8023551.js8
-rw-r--r--test/script/basic/JDK-8023630.js10
-rw-r--r--test/script/basic/JDK-8023650.js8
-rw-r--r--test/script/basic/JDK-8023780.js8
-rw-r--r--test/script/basic/JDK-8023784.js8
-rw-r--r--test/script/basic/JDK-8024120.js8
-rw-r--r--test/script/basic/JDK-8024174.js8
-rw-r--r--test/script/basic/JDK-8024255.js12
-rw-r--r--test/script/basic/JDK-8024512.js8
-rw-r--r--test/script/basic/JDK-8024619.js8
-rw-r--r--test/script/basic/JDK-8024846.js8
-rw-r--r--test/script/basic/JDK-8024847.js10
-rw-r--r--test/script/basic/JDK-8024972.js8
-rw-r--r--test/script/basic/JDK-8025048-2.js10
-rw-r--r--test/script/basic/JDK-8025048.js10
-rw-r--r--test/script/basic/JDK-8025080.js8
-rw-r--r--test/script/basic/JDK-8025090.js8
-rw-r--r--test/script/basic/JDK-8025111.js8
-rw-r--r--test/script/basic/JDK-8025147.js8
-rw-r--r--test/script/basic/JDK-8025149.js8
-rw-r--r--test/script/basic/JDK-8025163.js8
-rw-r--r--test/script/basic/JDK-8025197.js8
-rw-r--r--test/script/basic/JDK-8025213.js8
-rw-r--r--test/script/basic/JDK-8025312.js8
-rw-r--r--test/script/basic/JDK-8025325.js8
-rw-r--r--test/script/basic/JDK-8025434.js8
-rw-r--r--test/script/basic/JDK-8025486.js8
-rw-r--r--test/script/basic/JDK-8025488.js10
-rw-r--r--test/script/basic/JDK-8025515.js12
-rw-r--r--test/script/basic/JDK-8025520.js8
-rw-r--r--test/script/basic/JDK-8025589.js8
-rw-r--r--test/script/basic/JDK-8026008.js8
-rw-r--r--test/script/basic/JDK-8026016.js8
-rw-r--r--test/script/basic/JDK-8026033.js8
-rw-r--r--test/script/basic/JDK-8026042.js8
-rw-r--r--test/script/basic/JDK-8026048.js8
-rw-r--r--test/script/basic/JDK-8026112.js8
-rw-r--r--test/script/basic/JDK-8026125.js8
-rw-r--r--test/script/basic/JDK-8026137.js18
-rw-r--r--test/script/basic/JDK-8026161.js8
-rw-r--r--test/script/basic/JDK-8026162.js8
-rw-r--r--test/script/basic/JDK-8026167.js10
-rw-r--r--test/script/basic/JDK-8026248.js10
-rw-r--r--test/script/basic/JDK-8026264.js8
-rw-r--r--test/script/basic/JDK-8026292.js8
-rw-r--r--test/script/basic/JDK-8026302.js10
-rw-r--r--test/script/basic/JDK-8026317.js8
-rw-r--r--test/script/basic/JDK-8026367.js8
-rw-r--r--test/script/basic/JDK-8026692.js8
-rw-r--r--test/script/basic/JDK-8026693.js8
-rw-r--r--test/script/basic/JDK-8026701.js8
-rw-r--r--test/script/basic/JDK-8026805.js8
-rw-r--r--test/script/basic/JDK-8026858.js8
-rw-r--r--test/script/basic/JDK-8026955.js8
-rw-r--r--test/script/basic/JDK-8027016.js8
-rw-r--r--test/script/basic/JDK-8027024.js10
-rw-r--r--test/script/basic/JDK-8027042.js52
-rw-r--r--test/script/basic/JDK-8027042.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8027236.js8
-rw-r--r--test/script/basic/JDK-8027562.js8
-rw-r--r--test/script/basic/JDK-8027700.js10
-rw-r--r--test/script/basic/JDK-8027753.js8
-rw-r--r--test/script/basic/JDK-8027828.js8
-rw-r--r--test/script/basic/JDK-8027933.js8
-rw-r--r--test/script/basic/JDK-8028020.js8
-rw-r--r--test/script/basic/JDK-8028210.js8
-rw-r--r--test/script/basic/JDK-8028434.js20
-rw-r--r--test/script/basic/JDK-8029364.js8
-rw-r--r--test/script/basic/JDK-8029384.js (renamed from test/script/basic/runsunspider-eager.js)18
-rw-r--r--test/script/basic/JDK-8029384.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8029467.js9
-rw-r--r--test/script/basic/JDK-8029667.js18
-rw-r--r--test/script/basic/JDK-8030182.js8
-rw-r--r--test/script/basic/JDK-8030182_2.js14
-rw-r--r--test/script/basic/JDK-8030182_2.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8030197.js8
-rw-r--r--test/script/basic/JDK-8030199.js8
-rw-r--r--test/script/basic/JDK-8030200.js8
-rw-r--r--test/script/basic/JDK-8030202.js8
-rw-r--r--test/script/basic/JDK-8030809.js10
-rw-r--r--test/script/basic/JDK-8031317.js8
-rw-r--r--test/script/basic/JDK-8031359.js8
-rw-r--r--test/script/basic/JDK-8031983.js10
-rw-r--r--test/script/basic/JDK-8032004.js10
-rw-r--r--test/script/basic/JDK-8032068.js8
-rw-r--r--test/script/basic/JDK-8034055.js8
-rw-r--r--test/script/basic/JDK-8035312.js225
-rw-r--r--test/script/basic/JDK-8035312.js.EXPECTED186
-rw-r--r--test/script/basic/JDK-8035312_2.js65
-rw-r--r--test/script/basic/JDK-8035312_2.js.EXPECTED47
-rw-r--r--test/script/basic/JDK-8035312_3.js43
-rw-r--r--test/script/basic/JDK-8035312_3.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8035312_4.js59
-rw-r--r--test/script/basic/JDK-8035312_4.js.EXPECTED23
-rw-r--r--test/script/basic/JDK-8035312_5.js60
-rw-r--r--test/script/basic/JDK-8035312_5.js.EXPECTED6
-rw-r--r--test/script/basic/JDK-8037562.js8
-rw-r--r--test/script/basic/JDK-8038413.js38
-rw-r--r--test/script/basic/JDK-8038413.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8038945.js240
-rw-r--r--test/script/basic/JDK-8038945.js.EXPECTED40
-rw-r--r--test/script/basic/JDK-8039387.js8
-rw-r--r--test/script/basic/JDK-8040024.js100
-rw-r--r--test/script/basic/JDK-8040024.js.EXPECTED8
-rw-r--r--test/script/basic/JDK-8041995.js69
-rw-r--r--test/script/basic/JDK-8041995.js.EXPECTED9
-rw-r--r--test/script/basic/JDK-8041998.js8
-rw-r--r--test/script/basic/JDK-8042364.js10
-rw-r--r--test/script/basic/JDK-8043133.js41
-rw-r--r--test/script/basic/JDK-8043133.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8043232.js92
-rw-r--r--test/script/basic/JDK-8043232.js.EXPECTED14
-rw-r--r--test/script/basic/JDK-8043235.js58
-rw-r--r--test/script/basic/JDK-8043235.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8043431.js42
-rw-r--r--test/script/basic/JDK-8043431.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8043930.js10
-rw-r--r--test/script/basic/JDK-8044520.js8
-rw-r--r--test/script/basic/JDK-8044533.js (renamed from test/script/basic/ranges_disabled.js)17
-rw-r--r--test/script/basic/JDK-8044533.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8044534.js36
-rw-r--r--test/script/basic/JDK-8044534.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8044612.js2
-rw-r--r--test/script/basic/JDK-8044695.js8
-rw-r--r--test/script/basic/JDK-8044750.js8
-rw-r--r--test/script/basic/JDK-8046013.js57
-rw-r--r--test/script/basic/JDK-8046013.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8046026.js49
-rw-r--r--test/script/basic/JDK-8046026.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8046905.js91
-rw-r--r--test/script/basic/JDK-8046905.js.EXPECTED41
-rw-r--r--test/script/basic/JDK-8047035.js37
-rw-r--r--test/script/basic/JDK-8047035.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8047057.js75
-rw-r--r--test/script/basic/JDK-8047067.js36
-rw-r--r--test/script/basic/JDK-8047078.js38
-rw-r--r--test/script/basic/JDK-8047166.js31
-rw-r--r--test/script/basic/JDK-8047357.js32
-rw-r--r--test/script/basic/JDK-8047357.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8047359.js47
-rw-r--r--test/script/basic/JDK-8047369.js186
-rw-r--r--test/script/basic/JDK-8047371.js32
-rw-r--r--test/script/basic/JDK-8047371.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8047728.js54
-rw-r--r--test/script/basic/JDK-8047764-strict.js69
-rw-r--r--test/script/basic/JDK-8047764-strict.js.EXPECTED15
-rw-r--r--test/script/basic/JDK-8047764.js94
-rw-r--r--test/script/basic/JDK-8047764.js.EXPECTED30
-rw-r--r--test/script/basic/JDK-8047959.js59
-rw-r--r--test/script/basic/JDK-8047959.js.EXPECTED15
-rw-r--r--test/script/basic/JDK-8048071.js85
-rw-r--r--test/script/basic/JDK-8048071.js.EXPECTED11
-rw-r--r--test/script/basic/JDK-8048079_1a.js34
-rw-r--r--test/script/basic/JDK-8048079_1a.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8048079_1b.js34
-rw-r--r--test/script/basic/JDK-8048079_1b.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8048079_2a.js34
-rw-r--r--test/script/basic/JDK-8048079_2a.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8048079_2b.js34
-rw-r--r--test/script/basic/JDK-8048079_2b.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8048505.js52
-rw-r--r--test/script/basic/JDK-8048505.js.EXPECTED7
-rw-r--r--test/script/basic/JDK-8048586.js41
-rw-r--r--test/script/basic/JDK-8048718.js52
-rw-r--r--test/script/basic/JDK-8049086.js144
-rw-r--r--test/script/basic/JDK-8049086.js.EXPECTED48
-rw-r--r--test/script/basic/JDK-8049242.js78
-rw-r--r--test/script/basic/JDK-8049242.js.EXPECTED10
-rw-r--r--test/script/basic/JDK-8049407-big-endian.js33
-rw-r--r--test/script/basic/JDK-8049407-big-endian.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8049407-payload.js37
-rw-r--r--test/script/basic/JDK-8049407.js33
-rw-r--r--test/script/basic/JDK-8049407.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8050432.js40
-rw-r--r--test/script/basic/JDK-8051439.js52
-rw-r--r--test/script/basic/JDK-8051439.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8051778.js83
-rw-r--r--test/script/basic/JDK-8051778.js.EXPECTED10
-rw-r--r--test/script/basic/JDK-8054503.js50
-rw-r--r--test/script/basic/JDK-8055762.js84
-rw-r--r--test/script/basic/JDK-8055762.js.EXPECTED5
-rw-r--r--test/script/basic/JDK-8055796.js37
-rw-r--r--test/script/basic/JDK-8055796.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8055796_2.js79
-rw-r--r--test/script/basic/JDK-8055796_2.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8055870.js41
-rw-r--r--test/script/basic/JDK-8055870.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8056123.js45
-rw-r--r--test/script/basic/JDK-8056129.js42
-rw-r--r--test/script/basic/JDK-8056129.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8056978.js46
-rw-r--r--test/script/basic/JDK-8056978.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8057019-2.js33
-rw-r--r--test/script/basic/JDK-8057019-2.js.EXPECTED24
-rw-r--r--test/script/basic/JDK-8057019-payload.js102
-rw-r--r--test/script/basic/JDK-8057019.js35
-rw-r--r--test/script/basic/JDK-8057019.js.EXPECTED24
-rw-r--r--test/script/basic/JDK-8057825.js45
-rw-r--r--test/script/basic/JDK-8057825.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8058179.js48
-rw-r--r--test/script/basic/JDK-8058179.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8058422.js55
-rw-r--r--test/script/basic/JDK-8058545.js41
-rw-r--r--test/script/basic/JDK-8058561.js42
-rw-r--r--test/script/basic/JDK-8058610.js77
-rw-r--r--test/script/basic/JDK-8058610.js.EXPECTED18
-rw-r--r--test/script/basic/JDK-8058615.js36
-rw-r--r--test/script/basic/JDK-8058615.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8059443.js39
-rw-r--r--test/script/basic/JDK-8059443.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8060011.js58
-rw-r--r--test/script/basic/JDK-8060101.js54
-rw-r--r--test/script/basic/JDK-8061113.js35
-rw-r--r--test/script/basic/JDK-8061113.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8061391.js151
-rw-r--r--test/script/basic/JDK-8061391.js.EXPECTED138
-rw-r--r--test/script/basic/JDK-8061391_2.js52
-rw-r--r--test/script/basic/JDK-8061391_3.js44
-rw-r--r--test/script/basic/JDK-8061391_3.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8061959.js35
-rw-r--r--test/script/basic/JDK-8061959.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8062024.js40
-rw-r--r--test/script/basic/JDK-8062024.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8062132.js80
-rw-r--r--test/script/basic/JDK-8062132.js.EXPECTED6
-rw-r--r--test/script/basic/JDK-8062381.js53
-rw-r--r--test/script/basic/JDK-8062381.js.EXPECTED32
-rw-r--r--test/script/basic/JDK-8062583.js51
-rw-r--r--test/script/basic/JDK-8062583.js.EXPECTED8
-rw-r--r--test/script/basic/JDK-8062624.js45
-rw-r--r--test/script/basic/JDK-8062624.js.EXPECTED16
-rw-r--r--test/script/basic/JDK-8062799.js103
-rw-r--r--test/script/basic/JDK-8062799.js.EXPECTED50
-rw-r--r--test/script/basic/JDK-8062937.js46
-rw-r--r--test/script/basic/JDK-8062937.js.EXPECTED9
-rw-r--r--test/script/basic/JDK-8066221.js31
-rw-r--r--test/script/basic/JDK-8066224.js38
-rw-r--r--test/script/basic/JDK-8066224.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8066225.js36
-rw-r--r--test/script/basic/JDK-8066225.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8066227.js40
-rw-r--r--test/script/basic/JDK-8066227.js.EXPECTED10
-rw-r--r--test/script/basic/JDK-8066230.js34
-rw-r--r--test/script/basic/JDK-8066230.js.EXPECTED1
-rw-r--r--test/script/basic/JDK-8066236.js46
-rw-r--r--test/script/basic/JDK-8066236.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8066669.js58
-rw-r--r--test/script/basic/JDK-8066669.js.EXPECTED13
-rw-r--r--test/script/basic/JDK-8066932.js48
-rw-r--r--test/script/basic/JDK-8067136.js69
-rw-r--r--test/script/basic/JDK-8067136.js.EXPECTED1
-rw-r--r--test/script/basic/JDK_8005848.js2
-rw-r--r--test/script/basic/NASHORN-100.js8
-rw-r--r--test/script/basic/NASHORN-101.js8
-rw-r--r--test/script/basic/NASHORN-102.js8
-rw-r--r--test/script/basic/NASHORN-103.js8
-rw-r--r--test/script/basic/NASHORN-104.js8
-rw-r--r--test/script/basic/NASHORN-105.js10
-rw-r--r--test/script/basic/NASHORN-106.js8
-rw-r--r--test/script/basic/NASHORN-107.js8
-rw-r--r--test/script/basic/NASHORN-108.js8
-rw-r--r--test/script/basic/NASHORN-109.js8
-rw-r--r--test/script/basic/NASHORN-11.js8
-rw-r--r--test/script/basic/NASHORN-111.js10
-rw-r--r--test/script/basic/NASHORN-113.js8
-rw-r--r--test/script/basic/NASHORN-114.js8
-rw-r--r--test/script/basic/NASHORN-115.js8
-rw-r--r--test/script/basic/NASHORN-117.js10
-rw-r--r--test/script/basic/NASHORN-118.js10
-rw-r--r--test/script/basic/NASHORN-119.js8
-rw-r--r--test/script/basic/NASHORN-12.js8
-rw-r--r--test/script/basic/NASHORN-120.js8
-rw-r--r--test/script/basic/NASHORN-122.js8
-rw-r--r--test/script/basic/NASHORN-126.js12
-rw-r--r--test/script/basic/NASHORN-127.js18
-rw-r--r--test/script/basic/NASHORN-130.js8
-rw-r--r--test/script/basic/NASHORN-132.js8
-rw-r--r--test/script/basic/NASHORN-133.js8
-rw-r--r--test/script/basic/NASHORN-135.js8
-rw-r--r--test/script/basic/NASHORN-136.js10
-rw-r--r--test/script/basic/NASHORN-14.js10
-rw-r--r--test/script/basic/NASHORN-148.js14
-rw-r--r--test/script/basic/NASHORN-15.js8
-rw-r--r--test/script/basic/NASHORN-153.js8
-rw-r--r--test/script/basic/NASHORN-156.js12
-rw-r--r--test/script/basic/NASHORN-157.js10
-rw-r--r--test/script/basic/NASHORN-163.js10
-rw-r--r--test/script/basic/NASHORN-164.js10
-rw-r--r--test/script/basic/NASHORN-165.js8
-rw-r--r--test/script/basic/NASHORN-166.js8
-rw-r--r--test/script/basic/NASHORN-168.js8
-rw-r--r--test/script/basic/NASHORN-169.js8
-rw-r--r--test/script/basic/NASHORN-172.js14
-rw-r--r--test/script/basic/NASHORN-173.js8
-rw-r--r--test/script/basic/NASHORN-174.js10
-rw-r--r--test/script/basic/NASHORN-175.js8
-rw-r--r--test/script/basic/NASHORN-176.js8
-rw-r--r--test/script/basic/NASHORN-177.js10
-rw-r--r--test/script/basic/NASHORN-178.js8
-rw-r--r--test/script/basic/NASHORN-179.js8
-rw-r--r--test/script/basic/NASHORN-18.js8
-rw-r--r--test/script/basic/NASHORN-181.js10
-rw-r--r--test/script/basic/NASHORN-182.js10
-rw-r--r--test/script/basic/NASHORN-183.js8
-rw-r--r--test/script/basic/NASHORN-184.js8
-rw-r--r--test/script/basic/NASHORN-185.js8
-rw-r--r--test/script/basic/NASHORN-187.js16
-rw-r--r--test/script/basic/NASHORN-188.js8
-rw-r--r--test/script/basic/NASHORN-19.js232
-rw-r--r--test/script/basic/NASHORN-190.js10
-rw-r--r--test/script/basic/NASHORN-192.js12
-rw-r--r--test/script/basic/NASHORN-194.js8
-rw-r--r--test/script/basic/NASHORN-196.js10
-rw-r--r--test/script/basic/NASHORN-198.js8
-rw-r--r--test/script/basic/NASHORN-20.js8
-rw-r--r--test/script/basic/NASHORN-201.js8
-rw-r--r--test/script/basic/NASHORN-202.js8
-rw-r--r--test/script/basic/NASHORN-203.js8
-rw-r--r--test/script/basic/NASHORN-204.js8
-rw-r--r--test/script/basic/NASHORN-205.js10
-rw-r--r--test/script/basic/NASHORN-206.js8
-rw-r--r--test/script/basic/NASHORN-207.js12
-rw-r--r--test/script/basic/NASHORN-207_2.js8
-rw-r--r--test/script/basic/NASHORN-208.js10
-rw-r--r--test/script/basic/NASHORN-209.js12
-rw-r--r--test/script/basic/NASHORN-21.js8
-rw-r--r--test/script/basic/NASHORN-211.js8
-rw-r--r--test/script/basic/NASHORN-212.js8
-rw-r--r--test/script/basic/NASHORN-213.js8
-rw-r--r--test/script/basic/NASHORN-215.js8
-rw-r--r--test/script/basic/NASHORN-216.js8
-rw-r--r--test/script/basic/NASHORN-217.js8
-rw-r--r--test/script/basic/NASHORN-219.js8
-rw-r--r--test/script/basic/NASHORN-22.js8
-rw-r--r--test/script/basic/NASHORN-221.js8
-rw-r--r--test/script/basic/NASHORN-222.js8
-rw-r--r--test/script/basic/NASHORN-223.js8
-rw-r--r--test/script/basic/NASHORN-225.js8
-rw-r--r--test/script/basic/NASHORN-226.js8
-rw-r--r--test/script/basic/NASHORN-227.js8
-rw-r--r--test/script/basic/NASHORN-228.js10
-rw-r--r--test/script/basic/NASHORN-229.js10
-rw-r--r--test/script/basic/NASHORN-229_subtest.js10
-rw-r--r--test/script/basic/NASHORN-23.js10
-rw-r--r--test/script/basic/NASHORN-232.js8
-rw-r--r--test/script/basic/NASHORN-234.js8
-rw-r--r--test/script/basic/NASHORN-235.js8
-rw-r--r--test/script/basic/NASHORN-236.js8
-rw-r--r--test/script/basic/NASHORN-237.js8
-rw-r--r--test/script/basic/NASHORN-239.js8
-rw-r--r--test/script/basic/NASHORN-24.js10
-rw-r--r--test/script/basic/NASHORN-241.js16
-rw-r--r--test/script/basic/NASHORN-242.js8
-rw-r--r--test/script/basic/NASHORN-245.js8
-rw-r--r--test/script/basic/NASHORN-247.js8
-rw-r--r--test/script/basic/NASHORN-25.js8
-rw-r--r--test/script/basic/NASHORN-251.js8
-rw-r--r--test/script/basic/NASHORN-252.js8
-rw-r--r--test/script/basic/NASHORN-253.js8
-rw-r--r--test/script/basic/NASHORN-256.js8
-rw-r--r--test/script/basic/NASHORN-258.js52
-rw-r--r--test/script/basic/NASHORN-26.js8
-rw-r--r--test/script/basic/NASHORN-260.js8
-rw-r--r--test/script/basic/NASHORN-261.js10
-rw-r--r--test/script/basic/NASHORN-262.js10
-rw-r--r--test/script/basic/NASHORN-263.js8
-rw-r--r--test/script/basic/NASHORN-264.js8
-rw-r--r--test/script/basic/NASHORN-265.js10
-rw-r--r--test/script/basic/NASHORN-266.js8
-rw-r--r--test/script/basic/NASHORN-269.js8
-rw-r--r--test/script/basic/NASHORN-27.js8
-rw-r--r--test/script/basic/NASHORN-270.js8
-rw-r--r--test/script/basic/NASHORN-271.js14
-rw-r--r--test/script/basic/NASHORN-275.js8
-rw-r--r--test/script/basic/NASHORN-276.js8
-rw-r--r--test/script/basic/NASHORN-277.js8
-rw-r--r--test/script/basic/NASHORN-278.js8
-rw-r--r--test/script/basic/NASHORN-28.js8
-rw-r--r--test/script/basic/NASHORN-281.js8
-rw-r--r--test/script/basic/NASHORN-284.js8
-rw-r--r--test/script/basic/NASHORN-285.js44
-rw-r--r--test/script/basic/NASHORN-288.js8
-rw-r--r--test/script/basic/NASHORN-29.js8
-rw-r--r--test/script/basic/NASHORN-293.js8
-rw-r--r--test/script/basic/NASHORN-294.js8
-rw-r--r--test/script/basic/NASHORN-296.js8
-rw-r--r--test/script/basic/NASHORN-297.js8
-rw-r--r--test/script/basic/NASHORN-30.js14
-rw-r--r--test/script/basic/NASHORN-300.js12
-rw-r--r--test/script/basic/NASHORN-301.js8
-rw-r--r--test/script/basic/NASHORN-304.js8
-rw-r--r--test/script/basic/NASHORN-310.js8
-rw-r--r--test/script/basic/NASHORN-318.js8
-rw-r--r--test/script/basic/NASHORN-32.js8
-rw-r--r--test/script/basic/NASHORN-321.js8
-rw-r--r--test/script/basic/NASHORN-323.js8
-rw-r--r--test/script/basic/NASHORN-324.js8
-rw-r--r--test/script/basic/NASHORN-33.js8
-rw-r--r--test/script/basic/NASHORN-331.js10
-rw-r--r--test/script/basic/NASHORN-337.js10
-rw-r--r--test/script/basic/NASHORN-34.js8
-rw-r--r--test/script/basic/NASHORN-340.js8
-rw-r--r--test/script/basic/NASHORN-349.js8
-rw-r--r--test/script/basic/NASHORN-354.js8
-rw-r--r--test/script/basic/NASHORN-355.js8
-rw-r--r--test/script/basic/NASHORN-36.js8
-rw-r--r--test/script/basic/NASHORN-365.js8
-rw-r--r--test/script/basic/NASHORN-366.js8
-rw-r--r--test/script/basic/NASHORN-368.js8
-rw-r--r--test/script/basic/NASHORN-37.js10
-rw-r--r--test/script/basic/NASHORN-375.js8
-rw-r--r--test/script/basic/NASHORN-376.js8
-rw-r--r--test/script/basic/NASHORN-377-big-endian.js33
-rw-r--r--test/script/basic/NASHORN-377-big-endian.js.EXPECTED34
-rw-r--r--test/script/basic/NASHORN-377-payload.js226
-rw-r--r--test/script/basic/NASHORN-377.js207
-rw-r--r--test/script/basic/NASHORN-378.js10
-rw-r--r--test/script/basic/NASHORN-38.js10
-rw-r--r--test/script/basic/NASHORN-380.js8
-rw-r--r--test/script/basic/NASHORN-381.js8
-rw-r--r--test/script/basic/NASHORN-382.js8
-rw-r--r--test/script/basic/NASHORN-383.js8
-rw-r--r--test/script/basic/NASHORN-384.js8
-rw-r--r--test/script/basic/NASHORN-385.js14
-rw-r--r--test/script/basic/NASHORN-389.js8
-rw-r--r--test/script/basic/NASHORN-393.js8
-rw-r--r--test/script/basic/NASHORN-394.js8
-rw-r--r--test/script/basic/NASHORN-396.js18
-rw-r--r--test/script/basic/NASHORN-397.js8
-rw-r--r--test/script/basic/NASHORN-398.js8
-rw-r--r--test/script/basic/NASHORN-40.js8
-rw-r--r--test/script/basic/NASHORN-400.js8
-rw-r--r--test/script/basic/NASHORN-401.js8
-rw-r--r--test/script/basic/NASHORN-402.js8
-rw-r--r--test/script/basic/NASHORN-404.js8
-rw-r--r--test/script/basic/NASHORN-405.js12
-rw-r--r--test/script/basic/NASHORN-406.js16
-rw-r--r--test/script/basic/NASHORN-408.js8
-rw-r--r--test/script/basic/NASHORN-415.js8
-rw-r--r--test/script/basic/NASHORN-416.js10
-rw-r--r--test/script/basic/NASHORN-417.js8
-rw-r--r--test/script/basic/NASHORN-418.js8
-rw-r--r--test/script/basic/NASHORN-420.js8
-rw-r--r--test/script/basic/NASHORN-421.js12
-rw-r--r--test/script/basic/NASHORN-423.js8
-rw-r--r--test/script/basic/NASHORN-423a.js8
-rw-r--r--test/script/basic/NASHORN-424.js8
-rw-r--r--test/script/basic/NASHORN-425.js8
-rw-r--r--test/script/basic/NASHORN-426.js8
-rw-r--r--test/script/basic/NASHORN-427.js8
-rw-r--r--test/script/basic/NASHORN-428.js8
-rw-r--r--test/script/basic/NASHORN-429.js8
-rw-r--r--test/script/basic/NASHORN-432.js8
-rw-r--r--test/script/basic/NASHORN-433.js8
-rw-r--r--test/script/basic/NASHORN-434.js12
-rw-r--r--test/script/basic/NASHORN-435.js8
-rw-r--r--test/script/basic/NASHORN-437.js8
-rw-r--r--test/script/basic/NASHORN-44.js18
-rw-r--r--test/script/basic/NASHORN-441.js8
-rw-r--r--test/script/basic/NASHORN-442.js8
-rw-r--r--test/script/basic/NASHORN-443.js8
-rw-r--r--test/script/basic/NASHORN-444.js8
-rw-r--r--test/script/basic/NASHORN-445.js8
-rw-r--r--test/script/basic/NASHORN-446.js8
-rw-r--r--test/script/basic/NASHORN-447.js8
-rw-r--r--test/script/basic/NASHORN-448.js8
-rw-r--r--test/script/basic/NASHORN-449.js10
-rw-r--r--test/script/basic/NASHORN-45.js8
-rw-r--r--test/script/basic/NASHORN-450.js8
-rw-r--r--test/script/basic/NASHORN-452.js8
-rw-r--r--test/script/basic/NASHORN-459.js8
-rw-r--r--test/script/basic/NASHORN-46.js8
-rw-r--r--test/script/basic/NASHORN-462.js12
-rw-r--r--test/script/basic/NASHORN-463.js8
-rw-r--r--test/script/basic/NASHORN-468.js8
-rw-r--r--test/script/basic/NASHORN-47.js8
-rw-r--r--test/script/basic/NASHORN-473.js8
-rw-r--r--test/script/basic/NASHORN-474.js8
-rw-r--r--test/script/basic/NASHORN-478.js8
-rw-r--r--test/script/basic/NASHORN-48.js28
-rw-r--r--test/script/basic/NASHORN-481.js10
-rw-r--r--test/script/basic/NASHORN-482.js8
-rw-r--r--test/script/basic/NASHORN-484.js8
-rw-r--r--test/script/basic/NASHORN-486.js10
-rw-r--r--test/script/basic/NASHORN-487.js8
-rw-r--r--test/script/basic/NASHORN-488.js10
-rw-r--r--test/script/basic/NASHORN-49.js8
-rw-r--r--test/script/basic/NASHORN-490.js8
-rw-r--r--test/script/basic/NASHORN-494.js8
-rw-r--r--test/script/basic/NASHORN-497.js8
-rw-r--r--test/script/basic/NASHORN-498.js12
-rw-r--r--test/script/basic/NASHORN-499.js8
-rw-r--r--test/script/basic/NASHORN-50.js12
-rw-r--r--test/script/basic/NASHORN-500.js10
-rw-r--r--test/script/basic/NASHORN-503.js8
-rw-r--r--test/script/basic/NASHORN-51.js8
-rw-r--r--test/script/basic/NASHORN-511.js8
-rw-r--r--test/script/basic/NASHORN-515.js86
-rw-r--r--test/script/basic/NASHORN-516.js8
-rw-r--r--test/script/basic/NASHORN-52.js8
-rw-r--r--test/script/basic/NASHORN-534.js8
-rw-r--r--test/script/basic/NASHORN-535.js8
-rw-r--r--test/script/basic/NASHORN-544.js8
-rw-r--r--test/script/basic/NASHORN-55.js8
-rw-r--r--test/script/basic/NASHORN-554.js8
-rw-r--r--test/script/basic/NASHORN-556.js8
-rw-r--r--test/script/basic/NASHORN-56.js8
-rw-r--r--test/script/basic/NASHORN-562.js8
-rw-r--r--test/script/basic/NASHORN-565.js8
-rw-r--r--test/script/basic/NASHORN-575.js8
-rw-r--r--test/script/basic/NASHORN-58.js118
-rw-r--r--test/script/basic/NASHORN-59.js8
-rw-r--r--test/script/basic/NASHORN-592-dual.js8
-rw-r--r--test/script/basic/NASHORN-592.js8
-rw-r--r--test/script/basic/NASHORN-597.js8
-rw-r--r--test/script/basic/NASHORN-60.js8
-rw-r--r--test/script/basic/NASHORN-609.js8
-rw-r--r--test/script/basic/NASHORN-61.js8
-rw-r--r--test/script/basic/NASHORN-62.js8
-rw-r--r--test/script/basic/NASHORN-620.js8
-rw-r--r--test/script/basic/NASHORN-623.js8
-rw-r--r--test/script/basic/NASHORN-627.js8
-rw-r--r--test/script/basic/NASHORN-63.js10
-rw-r--r--test/script/basic/NASHORN-637.js8
-rw-r--r--test/script/basic/NASHORN-639.js8
-rw-r--r--test/script/basic/NASHORN-64.js8
-rw-r--r--test/script/basic/NASHORN-642.js8
-rw-r--r--test/script/basic/NASHORN-646.js8
-rw-r--r--test/script/basic/NASHORN-658.js8
-rw-r--r--test/script/basic/NASHORN-659.js8
-rw-r--r--test/script/basic/NASHORN-66.js8
-rw-r--r--test/script/basic/NASHORN-664.js12
-rw-r--r--test/script/basic/NASHORN-665.js8
-rw-r--r--test/script/basic/NASHORN-67.js24
-rw-r--r--test/script/basic/NASHORN-678.js10
-rw-r--r--test/script/basic/NASHORN-68.js8
-rw-r--r--test/script/basic/NASHORN-689.js8
-rw-r--r--test/script/basic/NASHORN-69.js8
-rw-r--r--test/script/basic/NASHORN-691.js8
-rw-r--r--test/script/basic/NASHORN-694.js8
-rw-r--r--test/script/basic/NASHORN-697.js8
-rw-r--r--test/script/basic/NASHORN-703.js10
-rw-r--r--test/script/basic/NASHORN-703a.js10
-rw-r--r--test/script/basic/NASHORN-705.js8
-rw-r--r--test/script/basic/NASHORN-71.js8
-rw-r--r--test/script/basic/NASHORN-710.js8
-rw-r--r--test/script/basic/NASHORN-711.js8
-rw-r--r--test/script/basic/NASHORN-72.js8
-rw-r--r--test/script/basic/NASHORN-722.js8
-rw-r--r--test/script/basic/NASHORN-73.js38
-rw-r--r--test/script/basic/NASHORN-737.js8
-rw-r--r--test/script/basic/NASHORN-737.js.EXPECTED10
-rw-r--r--test/script/basic/NASHORN-74.js8
-rw-r--r--test/script/basic/NASHORN-740.js8
-rw-r--r--test/script/basic/NASHORN-75.js8
-rw-r--r--test/script/basic/NASHORN-758.js8
-rw-r--r--test/script/basic/NASHORN-759.js8
-rw-r--r--test/script/basic/NASHORN-760.js12
-rw-r--r--test/script/basic/NASHORN-768.js10
-rw-r--r--test/script/basic/NASHORN-778.js8
-rw-r--r--test/script/basic/NASHORN-78.js8
-rw-r--r--test/script/basic/NASHORN-79.js12
-rw-r--r--test/script/basic/NASHORN-792.js8
-rw-r--r--test/script/basic/NASHORN-80.js8
-rw-r--r--test/script/basic/NASHORN-81.js8
-rw-r--r--test/script/basic/NASHORN-833.js8
-rw-r--r--test/script/basic/NASHORN-837.js8
-rw-r--r--test/script/basic/NASHORN-85.js8
-rw-r--r--test/script/basic/NASHORN-86.js8
-rw-r--r--test/script/basic/NASHORN-87.js8
-rw-r--r--test/script/basic/NASHORN-89.js8
-rw-r--r--test/script/basic/NASHORN-90.js8
-rw-r--r--test/script/basic/NASHORN-91.js8
-rw-r--r--test/script/basic/NASHORN-92.js8
-rw-r--r--test/script/basic/NASHORN-93.js8
-rw-r--r--test/script/basic/NASHORN-95.js8
-rw-r--r--test/script/basic/NASHORN-96.js8
-rw-r--r--test/script/basic/NASHORN-97.js8
-rw-r--r--test/script/basic/NASHORN-98.js12
-rw-r--r--test/script/basic/NASHORN-99.js8
-rw-r--r--test/script/basic/access-specializer.js12
-rw-r--r--test/script/basic/addition.js8
-rw-r--r--test/script/basic/allgettersetters.js8
-rw-r--r--test/script/basic/andor.js10
-rw-r--r--test/script/basic/anonrecur.js8
-rw-r--r--test/script/basic/apply_to_call/apply_to_call1.js66
-rw-r--r--test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED8
-rw-r--r--test/script/basic/apply_to_call/apply_to_call2.js63
-rw-r--r--test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED8
-rw-r--r--test/script/basic/apply_to_call/apply_to_call3.js67
-rw-r--r--test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED9
-rw-r--r--test/script/basic/apply_to_call/apply_to_call4.js131
-rw-r--r--test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED31
-rw-r--r--test/script/basic/apply_to_call/apply_to_call5.js111
-rw-r--r--test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED19
-rw-r--r--test/script/basic/apply_to_call/apply_to_call_recompile.js44
-rw-r--r--test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED6
-rw-r--r--test/script/basic/apply_to_call/apply_to_call_varargs.js75
-rw-r--r--test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED66
-rw-r--r--test/script/basic/applycall.js8
-rw-r--r--test/script/basic/args.js8
-rw-r--r--test/script/basic/arity.js10
-rw-r--r--test/script/basic/arrayprotoclass.js8
-rw-r--r--test/script/basic/arrays.js10
-rw-r--r--test/script/basic/arrays2.js8
-rw-r--r--test/script/basic/arrays_int_key.js (renamed from test/script/basic/arraysIntKey.js)10
-rw-r--r--test/script/basic/arrays_int_key.js.EXPECTED (renamed from test/script/basic/arraysIntKey.js.EXPECTED)0
-rw-r--r--test/script/basic/arrayset.js10
-rw-r--r--test/script/basic/arrayundefined.js8
-rw-r--r--test/script/basic/assign.js10
-rw-r--r--test/script/basic/bitwise_and.js8
-rw-r--r--test/script/basic/boolean_arithmetic.js113
-rw-r--r--test/script/basic/boolean_arithmetic.js.EXPECTED60
-rw-r--r--test/script/basic/booleangetter.js8
-rw-r--r--test/script/basic/builtin.js8
-rw-r--r--test/script/basic/builtin_assign.js8
-rw-r--r--test/script/basic/builtinchain.js8
-rw-r--r--test/script/basic/calllink.js14
-rw-r--r--test/script/basic/classloader.js8
-rw-r--r--test/script/basic/closure.js16
-rw-r--r--test/script/basic/closure.js.EXPECTED4
-rw-r--r--test/script/basic/commandargs.js12
-rw-r--r--test/script/basic/compile-octane-normal.js42
-rw-r--r--test/script/basic/compile-octane-normal.js.EXPECTED30
-rw-r--r--test/script/basic/compile-octane-splitter.js26
-rw-r--r--test/script/basic/compile-octane-splitter.js.EXPECTED44
-rw-r--r--test/script/basic/compile-octane.js131
-rw-r--r--test/script/basic/compile-octane.js.EXPECTED14
-rw-r--r--test/script/basic/condassign.js8
-rw-r--r--test/script/basic/construct.js18
-rw-r--r--test/script/basic/constructorname.js8
-rw-r--r--test/script/basic/convert.js10
-rw-r--r--test/script/basic/dataview_endian.js8
-rw-r--r--test/script/basic/dataview_getset.js8
-rw-r--r--test/script/basic/dataview_new.js11
-rw-r--r--test/script/basic/date.js8
-rw-r--r--test/script/basic/dateparse.js8
-rw-r--r--test/script/basic/decinc.js8
-rw-r--r--test/script/basic/delete.js8
-rw-r--r--test/script/basic/delete2.js12
-rw-r--r--test/script/basic/dotpropname.js8
-rw-r--r--test/script/basic/doublecache.js12
-rw-r--r--test/script/basic/enumeration.js10
-rw-r--r--test/script/basic/errors.js10
-rw-r--r--test/script/basic/errorstack.js10
-rw-r--r--test/script/basic/es6/block-function-decl.js51
-rw-r--r--test/script/basic/es6/block-function-decl.js.EXPECTED10
-rw-r--r--test/script/basic/es6/const-empty.js37
-rw-r--r--test/script/basic/es6/const-empty.js.EXPECTED3
-rw-r--r--test/script/basic/es6/const-reassign.js174
-rw-r--r--test/script/basic/es6/const-reassign.js.EXPECTED16
-rw-r--r--test/script/basic/es6/const-redeclare-extra.js59
-rw-r--r--test/script/basic/es6/const-redeclare-extra.js.EXPECTED9
-rw-r--r--test/script/basic/es6/const-redeclare.js38
-rw-r--r--test/script/basic/es6/const-redeclare.js.EXPECTED3
-rw-r--r--test/script/basic/es6/const-self.js42
-rw-r--r--test/script/basic/es6/const-self.js.EXPECTED2
-rw-r--r--test/script/basic/es6/const-tdz.js81
-rw-r--r--test/script/basic/es6/const-tdz.js.EXPECTED9
-rw-r--r--test/script/basic/es6/const.js69
-rw-r--r--test/script/basic/es6/const.js.EXPECTED10
-rw-r--r--test/script/basic/es6/for-let-object-fields.js81
-rw-r--r--test/script/basic/es6/for-let-object-fields.js.EXPECTED33
-rw-r--r--test/script/basic/es6/for-let.js79
-rw-r--r--test/script/basic/es6/for-let.js.EXPECTED33
-rw-r--r--test/script/basic/es6/let-const-statement-context.js49
-rw-r--r--test/script/basic/es6/let-const-statement-context.js.EXPECTED30
-rw-r--r--test/script/basic/es6/let-const-switch.js45
-rw-r--r--test/script/basic/es6/let-const-switch.js.EXPECTED12
-rw-r--r--test/script/basic/es6/let-eval.js98
-rw-r--r--test/script/basic/es6/let-eval.js.EXPECTED16
-rw-r--r--test/script/basic/es6/let-load-lib.js48
-rw-r--r--test/script/basic/es6/let-load.js60
-rw-r--r--test/script/basic/es6/let-load.js.EXPECTED9
-rw-r--r--test/script/basic/es6/let-nodeclare.js52
-rw-r--r--test/script/basic/es6/let-nodeclare.js.EXPECTED4
-rw-r--r--test/script/basic/es6/let-redeclare-extra.js70
-rw-r--r--test/script/basic/es6/let-redeclare-extra.js.EXPECTED15
-rw-r--r--test/script/basic/es6/let-redeclare.js38
-rw-r--r--test/script/basic/es6/let-redeclare.js.EXPECTED3
-rw-r--r--test/script/basic/es6/let-self.js42
-rw-r--r--test/script/basic/es6/let-self.js.EXPECTED2
-rw-r--r--test/script/basic/es6/let-tdz.js97
-rw-r--r--test/script/basic/es6/let-tdz.js.EXPECTED12
-rw-r--r--test/script/basic/es6/let.js69
-rw-r--r--test/script/basic/es6/let.js.EXPECTED10
-rw-r--r--test/script/basic/es6/let_const_closure.js123
-rw-r--r--test/script/basic/es6/let_const_closure.js.EXPECTED13
-rw-r--r--test/script/basic/es6/let_const_reuse.js71
-rw-r--r--test/script/basic/es6/let_const_reuse.js.EXPECTED8
-rw-r--r--test/script/basic/es6/let_different_types.js73
-rw-r--r--test/script/basic/es6/let_different_types.js.EXPECTED13
-rw-r--r--test/script/basic/es6/let_loops.js80
-rw-r--r--test/script/basic/es6/let_loops.js.EXPECTED8
-rw-r--r--test/script/basic/es6/lexical-toplevel-def.js34
-rw-r--r--test/script/basic/es6/lexical-toplevel-print.js51
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js31
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js30
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js31
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js30
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js31
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js31
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare.js78
-rw-r--r--test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED100
-rw-r--r--test/script/basic/es6/lexical-toplevel.js35
-rw-r--r--test/script/basic/es6/lexical-toplevel.js.EXPECTED32
-rw-r--r--test/script/basic/eval.js14
-rw-r--r--test/script/basic/evalreturn.js12
-rw-r--r--test/script/basic/exprclosure.js8
-rw-r--r--test/script/basic/exprclosure.js.EXPECTED4
-rw-r--r--test/script/basic/extensibility.js8
-rw-r--r--test/script/basic/fastpushpop.js61
-rw-r--r--test/script/basic/fastpushpop.js.EXPECTED6
-rw-r--r--test/script/basic/fileline.js8
-rw-r--r--test/script/basic/finally-catchalls.js80
-rw-r--r--test/script/basic/finallyreturn.js8
-rw-r--r--test/script/basic/forin.js8
-rw-r--r--test/script/basic/forin2.js44
-rw-r--r--test/script/basic/funcarray.js14
-rw-r--r--test/script/basic/funcbind.js14
-rw-r--r--test/script/basic/funcbind2.js8
-rw-r--r--test/script/basic/funcbind3.js8
-rw-r--r--test/script/basic/funcconstructor.js8
-rw-r--r--test/script/basic/getclassname.js8
-rw-r--r--test/script/basic/getter_callsite.js12
-rw-r--r--test/script/basic/gettercalls.js8
-rw-r--r--test/script/basic/getterfunc.js8
-rw-r--r--test/script/basic/gettersetter.js14
-rw-r--r--test/script/basic/globalaccess.js8
-rw-r--r--test/script/basic/globals.js8
-rw-r--r--test/script/basic/globalscope.js10
-rw-r--r--test/script/basic/hello.js10
-rw-r--r--test/script/basic/herestr_operator.js8
-rw-r--r--test/script/basic/hideLocationProperties.js57
-rw-r--r--test/script/basic/hideLocationProperties.js.EXPECTED6
-rw-r--r--test/script/basic/illegaljavaname.js8
-rw-r--r--test/script/basic/importpackage.js8
-rw-r--r--test/script/basic/incheck.js12
-rw-r--r--test/script/basic/indexedcall.js8
-rw-r--r--test/script/basic/info.js8
-rw-r--r--test/script/basic/inherited_nonwritable.js8
-rw-r--r--test/script/basic/instanceof.js8
-rw-r--r--test/script/basic/instanceof2.js10
-rw-r--r--test/script/basic/interfaces.js10
-rw-r--r--test/script/basic/iterator.js10
-rw-r--r--test/script/basic/java.js8
-rw-r--r--test/script/basic/javaadapter.js8
-rw-r--r--test/script/basic/javaarray.js8
-rw-r--r--test/script/basic/javaarrayconversion.js16
-rw-r--r--test/script/basic/javaclassoverrides.js8
-rw-r--r--test/script/basic/javaexceptions.js10
-rw-r--r--test/script/basic/javaimporter.js10
-rw-r--r--test/script/basic/javainnerclasses.js10
-rw-r--r--test/script/basic/javasigcall.js8
-rw-r--r--test/script/basic/jquery.js70
-rw-r--r--test/script/basic/jsadapter.js8
-rw-r--r--test/script/basic/jsadapterlink.js8
-rw-r--r--test/script/basic/json.js12
-rw-r--r--test/script/basic/list.js8
-rw-r--r--test/script/basic/list.js.EXPECTED2
-rw-r--r--test/script/basic/literal.js10
-rw-r--r--test/script/basic/load.js8
-rw-r--r--test/script/basic/loadedfile.js8
-rw-r--r--test/script/basic/localundef.js10
-rw-r--r--test/script/basic/map.js10
-rw-r--r--test/script/basic/math.js8
-rw-r--r--test/script/basic/minuszero.js8
-rw-r--r--test/script/basic/module.js10
-rw-r--r--test/script/basic/moduleload.js8
-rw-r--r--test/script/basic/nashorn2.js12
-rw-r--r--test/script/basic/natives.js10
-rw-r--r--test/script/basic/new.js10
-rw-r--r--test/script/basic/newexpr.js16
-rw-r--r--test/script/basic/newnew.js10
-rw-r--r--test/script/basic/no_line_numbers.js38
-rw-r--r--test/script/basic/nonconstructors.js8
-rw-r--r--test/script/basic/nosuchmethod.js10
-rw-r--r--test/script/basic/nosuchproperty.js8
-rw-r--r--test/script/basic/number.js8
-rw-r--r--test/script/basic/numberstring.js8
-rw-r--r--test/script/basic/objectprops.js12
-rw-r--r--test/script/basic/objects.js8
-rw-r--r--test/script/basic/octane-payload.js58
-rw-r--r--test/script/basic/optimistic_arithmetic_check_type.js77
-rw-r--r--test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED38
-rw-r--r--test/script/basic/optimistic_assignment_check_type.js54
-rw-r--r--test/script/basic/optimistic_assignment_check_type.js.EXPECTED14
-rw-r--r--test/script/basic/optimistic_check_type.js108
-rw-r--r--test/script/basic/optimistic_check_type.js.EXPECTED30
-rw-r--r--test/script/basic/optimistic_logical_check_type.js65
-rw-r--r--test/script/basic/optimistic_logical_check_type.js.EXPECTED28
-rw-r--r--test/script/basic/options.js8
-rw-r--r--test/script/basic/paramspec.js8
-rw-r--r--test/script/basic/parser/assignmentExpr.js8
-rw-r--r--test/script/basic/parser/binaryExpr.js8
-rw-r--r--test/script/basic/parser/breakStat.js8
-rw-r--r--test/script/basic/parser/breakStat.js.EXPECTED20
-rw-r--r--test/script/basic/parser/condExpr.js8
-rw-r--r--test/script/basic/parser/continueStat.js8
-rw-r--r--test/script/basic/parser/continueStat.js.EXPECTED20
-rw-r--r--test/script/basic/parser/debuggerStat.js8
-rw-r--r--test/script/basic/parser/functions.js8
-rw-r--r--test/script/basic/parser/ifStat.js8
-rw-r--r--test/script/basic/parser/labelledStat.js8
-rw-r--r--test/script/basic/parser/labelledStat.js.EXPECTED20
-rw-r--r--test/script/basic/parser/lhsExpr.js8
-rw-r--r--test/script/basic/parser/lhsExpr.js.EXPECTED40
-rw-r--r--test/script/basic/parser/loopStat.js8
-rw-r--r--test/script/basic/parser/objectLitExpr.js8
-rw-r--r--test/script/basic/parser/parenExpr.js8
-rw-r--r--test/script/basic/parser/primaryExpr.js8
-rw-r--r--test/script/basic/parser/returnStat.js8
-rw-r--r--test/script/basic/parser/switchStat.js8
-rw-r--r--test/script/basic/parser/throwStat.js8
-rw-r--r--test/script/basic/parser/tryCatchStat.js8
-rw-r--r--test/script/basic/parser/unaryExpr.js8
-rw-r--r--test/script/basic/parser/useStrict.js8
-rw-r--r--test/script/basic/parser/util.js8
-rw-r--r--test/script/basic/parser/varDecl.js8
-rw-r--r--test/script/basic/parser/withStat.js8
-rw-r--r--test/script/basic/propchange.js10
-rw-r--r--test/script/basic/propertycheck.js8
-rw-r--r--test/script/basic/prototype.js20
-rw-r--r--test/script/basic/pushpull.js8
-rw-r--r--test/script/basic/ranges_disabled.js.EXPECTED4
-rw-r--r--test/script/basic/ranges_enabled.js.EXPECTED4
-rw-r--r--test/script/basic/regex.js12
-rw-r--r--test/script/basic/regexp_flags.js10
-rw-r--r--test/script/basic/relink_index_getter.js (renamed from test/script/basic/ranges_enabled.js)18
-rw-r--r--test/script/basic/relink_index_getter.js.EXPECTED2
-rw-r--r--test/script/basic/run-octane.js305
-rw-r--r--test/script/basic/runsunspider.js481
-rw-r--r--test/script/basic/runsunspider.js.EXPECTED (renamed from test/script/basic/runsunspider-lazy.js.EXPECTED)0
-rw-r--r--test/script/basic/samfunc.js10
-rw-r--r--test/script/basic/scripting.js8
-rw-r--r--test/script/basic/scripting.js.EXPECTED8
-rw-r--r--test/script/basic/sealfreeze.js8
-rw-r--r--test/script/basic/setlength.js10
-rw-r--r--test/script/basic/splitter.js10
-rw-r--r--test/script/basic/splitter.js.EXPECTED3
-rw-r--r--test/script/basic/splitter_prototype.js (renamed from test/script/basic/runsunspider-lazy.js)19
-rw-r--r--test/script/basic/splitter_prototype.js.EXPECTED1
-rw-r--r--test/script/basic/splitter_yui.js33
-rw-r--r--test/script/basic/splitter_yui.js.EXPECTED2
-rw-r--r--test/script/basic/stdin.js8
-rw-r--r--test/script/basic/strings.js8
-rw-r--r--test/script/basic/throws.js8
-rw-r--r--test/script/basic/tosource.js8
-rw-r--r--test/script/basic/tostring.js8
-rw-r--r--test/script/basic/try.js14
-rw-r--r--test/script/basic/try2.js26
-rw-r--r--test/script/basic/trybreakcont.js8
-rw-r--r--test/script/basic/trycatch.js14
-rw-r--r--test/script/basic/trycatchfor.js10
-rw-r--r--test/script/basic/tryfinallyreturn.js8
-rw-r--r--test/script/basic/tryforbreak.js12
-rw-r--r--test/script/basic/typechange.js10
-rw-r--r--test/script/basic/typecoerce.js24
-rw-r--r--test/script/basic/typedarrays.js42
-rw-r--r--test/script/basic/typedarrays2.js56
-rw-r--r--test/script/basic/typedarrays2.js.EXPECTED4
-rw-r--r--test/script/basic/typeof.js10
-rw-r--r--test/script/basic/typeof2.js8
-rw-r--r--test/script/basic/undefined.js8
-rw-r--r--test/script/basic/underscore.js10
-rw-r--r--test/script/basic/varargs.js10
-rw-r--r--test/script/basic/void.js8
-rw-r--r--test/script/basic/with.js20
-rw-r--r--test/script/basic/withprimitive.js10
-rw-r--r--test/script/basic/writable_relink.js8
-rw-r--r--test/script/basic/xorassign.js10
-rw-r--r--test/script/basic/yui.js24
-rw-r--r--test/script/currently-failing/JDK-8006191.js14
-rw-r--r--test/script/currently-failing/JDK-8010697.js (renamed from test/script/basic/JDK-8010697.js)6
-rw-r--r--test/script/currently-failing/JDK-8010697.js.EXPECTED (renamed from test/script/basic/JDK-8010697.js.EXPECTED)0
-rw-r--r--test/script/currently-failing/apply_to_call_bench.js93
-rw-r--r--test/script/currently-failing/apply_to_call_bench.js.EXPECTED6
-rw-r--r--test/script/currently-failing/clone_ir.js38
-rw-r--r--test/script/currently-failing/gettersetter.js8
-rw-r--r--test/script/currently-failing/logcoverage.js50
-rw-r--r--test/script/currently-failing/optimistic_check_type_cases.js42
-rw-r--r--test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED7
-rw-r--r--test/script/currently-failing/property_delete.js (renamed from test/script/maptests/property_delete.js)8
-rw-r--r--test/script/error/JDK-8008814-1.js8
-rw-r--r--test/script/error/JDK-8008814-2.js8
-rw-r--r--test/script/error/JDK-8016522.js8
-rw-r--r--test/script/error/JDK-8020437-2.js8
-rw-r--r--test/script/error/JDK-8020437.js8
-rw-r--r--test/script/error/JDK-8026039.js10
-rw-r--r--test/script/error/JDK-8026039.js.EXPECTED2
-rw-r--r--test/script/error/JDK-8027933.js8
-rw-r--r--test/script/error/JDK-8039047.js8
-rw-r--r--test/script/error/NASHORN-154/function_mult_params_in_strict.js12
-rw-r--r--test/script/error/NASHORN-154/improper_return_break_continue.js8
-rw-r--r--test/script/error/NASHORN-154/invalid_lvalue.js12
-rw-r--r--test/script/error/NASHORN-154/literal_data_and_accessor.js8
-rw-r--r--test/script/error/NASHORN-154/literal_mult_getters.js12
-rw-r--r--test/script/error/NASHORN-154/literal_mult_prop_in_strict.js10
-rw-r--r--test/script/error/NASHORN-154/with_in_strict.js8
-rw-r--r--test/script/error/NASHORN-214.js8
-rw-r--r--test/script/error/NASHORN-35.js8
-rw-r--r--test/script/error/NASHORN-39.js10
-rw-r--r--test/script/error/NASHORN-568.js8
-rw-r--r--test/script/error/NASHORN-57.js8
-rw-r--r--test/script/error/NASHORN-668.js8
-rw-r--r--test/script/error/quotemissing.js8
-rw-r--r--test/script/error/strictmode.js8
-rw-r--r--test/script/jfx/kaleidoscope.js166
-rw-r--r--test/script/jfx/spread.js2
-rw-r--r--test/script/maptests/builtins.js8
-rw-r--r--test/script/maptests/constructor.js10
-rw-r--r--test/script/maptests/maputil.js16
-rw-r--r--test/script/maptests/object_create.js8
-rw-r--r--test/script/maptests/object_literals.js12
-rw-r--r--test/script/maptests/point.js10
-rw-r--r--test/script/maptests/property_add.js10
-rw-r--r--test/script/maptests/proto.js8
-rw-r--r--test/script/markdown.js38
-rw-r--r--test/script/markdown/anchors-by-reference.js33
-rw-r--r--test/script/markdown/anchors-by-reference.js.EXPECTED4
-rw-r--r--test/script/markdown/automatic-anchors.js33
-rw-r--r--test/script/markdown/automatic-anchors.js.EXPECTED1
-rw-r--r--test/script/markdown/blockquote-nested-markdown.js33
-rw-r--r--test/script/markdown/blockquote-nested-markdown.js.EXPECTED13
-rw-r--r--test/script/markdown/blockquote.js33
-rw-r--r--test/script/markdown/blockquote.js.EXPECTED5
-rw-r--r--test/script/markdown/code-block-html-escape.js33
-rw-r--r--test/script/markdown/code-block-html-escape.js.EXPECTED4
-rw-r--r--test/script/markdown/code-block.js33
-rw-r--r--test/script/markdown/code-block.js.EXPECTED4
-rw-r--r--test/script/markdown/doubline-list.js33
-rw-r--r--test/script/markdown/doubline-list.js.EXPECTED4
-rw-r--r--test/script/markdown/emphasis.js33
-rw-r--r--test/script/markdown/emphasis.js.EXPECTED5
-rw-r--r--test/script/markdown/escaped-number-period.js33
-rw-r--r--test/script/markdown/escaped-number-period.js.EXPECTED1
-rw-r--r--test/script/markdown/escaping.js33
-rw-r--r--test/script/markdown/escaping.js.EXPECTED31
-rw-r--r--test/script/markdown/github-style-at-start.js33
-rw-r--r--test/script/markdown/github-style-at-start.js.EXPECTED6
-rw-r--r--test/script/markdown/github-style-codeblock.js33
-rw-r--r--test/script/markdown/github-style-codeblock.js.EXPECTED11
-rw-r--r--test/script/markdown/github-style-linebreaks.js33
-rw-r--r--test/script/markdown/github-style-linebreaks.js.EXPECTED3
-rw-r--r--test/script/markdown/h1-with-double-hash.js33
-rw-r--r--test/script/markdown/h1-with-double-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h1-with-equals.js33
-rw-r--r--test/script/markdown/h1-with-equals.js.EXPECTED1
-rw-r--r--test/script/markdown/h1-with-single-hash.js33
-rw-r--r--test/script/markdown/h1-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h2-with-dashes.js33
-rw-r--r--test/script/markdown/h2-with-dashes.js.EXPECTED1
-rw-r--r--test/script/markdown/h2-with-double-hash.js33
-rw-r--r--test/script/markdown/h2-with-double-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h2-with-single-hash.js33
-rw-r--r--test/script/markdown/h2-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h3-with-double-hash.js33
-rw-r--r--test/script/markdown/h3-with-double-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h3-with-single-hash.js33
-rw-r--r--test/script/markdown/h3-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h4-with-single-hash.js33
-rw-r--r--test/script/markdown/h4-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h5-with-single-hash.js33
-rw-r--r--test/script/markdown/h5-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/h6-with-single-hash.js33
-rw-r--r--test/script/markdown/h6-with-single-hash.js.EXPECTED1
-rw-r--r--test/script/markdown/horizontal-rules.js33
-rw-r--r--test/script/markdown/horizontal-rules.js.EXPECTED9
-rw-r--r--test/script/markdown/html5-strutural-tags.js33
-rw-r--r--test/script/markdown/html5-strutural-tags.js.EXPECTED22
-rw-r--r--test/script/markdown/images.js33
-rw-r--r--test/script/markdown/images.js.EXPECTED5
-rw-r--r--test/script/markdown/implicit-anchors.js33
-rw-r--r--test/script/markdown/implicit-anchors.js.EXPECTED1
-rw-r--r--test/script/markdown/inline-anchors.js33
-rw-r--r--test/script/markdown/inline-anchors.js.EXPECTED3
-rw-r--r--test/script/markdown/inline-code.js33
-rw-r--r--test/script/markdown/inline-code.js.EXPECTED11
-rw-r--r--test/script/markdown/inline-style-tag.js33
-rw-r--r--test/script/markdown/inline-style-tag.js.EXPECTED5
-rw-r--r--test/script/markdown/lazy-blockquote.js33
-rw-r--r--test/script/markdown/lazy-blockquote.js.EXPECTED5
-rw-r--r--test/script/markdown/list-with-blockquote.js33
-rw-r--r--test/script/markdown/list-with-blockquote.js.EXPECTED8
-rw-r--r--test/script/markdown/list-with-code.js33
-rw-r--r--test/script/markdown/list-with-code.js.EXPECTED6
-rw-r--r--test/script/markdown/multi-paragraph-list.js33
-rw-r--r--test/script/markdown/multi-paragraph-list.js.EXPECTED6
-rw-r--r--test/script/markdown/multiline-unordered-list.js33
-rw-r--r--test/script/markdown/multiline-unordered-list.js.EXPECTED5
-rw-r--r--test/script/markdown/nested-blockquote.js33
-rw-r--r--test/script/markdown/nested-blockquote.js.EXPECTED9
-rw-r--r--test/script/markdown/ordered-list-same-number.js33
-rw-r--r--test/script/markdown/ordered-list-same-number.js.EXPECTED5
-rw-r--r--test/script/markdown/ordered-list-wrong-numbers.js33
-rw-r--r--test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED5
-rw-r--r--test/script/markdown/ordered-list.js33
-rw-r--r--test/script/markdown/ordered-list.js.EXPECTED5
-rw-r--r--test/script/markdown/relative-anchors.js33
-rw-r--r--test/script/markdown/relative-anchors.js.EXPECTED1
-rw-r--r--test/script/markdown/simple-paragraph.js33
-rw-r--r--test/script/markdown/simple-paragraph.js.EXPECTED1
-rw-r--r--test/script/markdown/strong.js33
-rw-r--r--test/script/markdown/strong.js.EXPECTED5
-rw-r--r--test/script/markdown/table-basic.js33
-rw-r--r--test/script/markdown/table-basic.js.EXPECTED21
-rw-r--r--test/script/markdown/table-large.js33
-rw-r--r--test/script/markdown/table-large.js.EXPECTED48
-rw-r--r--test/script/markdown/table-with-equals.js33
-rw-r--r--test/script/markdown/table-with-equals.js.EXPECTED21
-rw-r--r--test/script/markdown/unordered-list-asterisk.js33
-rw-r--r--test/script/markdown/unordered-list-asterisk.js.EXPECTED5
-rw-r--r--test/script/markdown/unordered-list-minus.js33
-rw-r--r--test/script/markdown/unordered-list-minus.js.EXPECTED5
-rw-r--r--test/script/markdown/unordered-list-plus.js33
-rw-r--r--test/script/markdown/unordered-list-plus.js.EXPECTED5
-rw-r--r--test/script/markdown/url-with-parenthesis.js33
-rw-r--r--test/script/markdown/url-with-parenthesis.js.EXPECTED1
-rw-r--r--test/script/nosecurity/JDK-8044798.js22
-rw-r--r--test/script/nosecurity/JDK-8044798.js.EXPECTED92
-rw-r--r--test/script/nosecurity/JDK-8044851.js93
-rw-r--r--test/script/nosecurity/JDK-8044851.js.EXPECTED53
-rw-r--r--test/script/nosecurity/JDK-8050964.js59
-rw-r--r--test/script/nosecurity/JDK-8055034.js64
-rw-r--r--test/script/nosecurity/JDK-8055034.js.EXPECTED2
-rw-r--r--test/script/nosecurity/JDK-8055107.js179
-rw-r--r--test/script/nosecurity/JDK-8060688.js56
-rw-r--r--test/script/nosecurity/debuggersupportapi.js8
-rw-r--r--test/script/nosecurity/nosecurity.js10
-rw-r--r--test/script/sandbox/JDK-8031106.js8
-rw-r--r--test/script/sandbox/NASHORN-525.js10
-rw-r--r--test/script/sandbox/arrayclass.js8
-rw-r--r--test/script/sandbox/classbind.js8
-rw-r--r--test/script/sandbox/classloader.js8
-rw-r--r--test/script/sandbox/doprivileged.js16
-rw-r--r--test/script/sandbox/engine.js8
-rw-r--r--test/script/sandbox/env.js8
-rw-r--r--test/script/sandbox/exec.js8
-rw-r--r--test/script/sandbox/exit.js8
-rw-r--r--test/script/sandbox/file.js8
-rw-r--r--test/script/sandbox/interfaceimpl.js8
-rw-r--r--test/script/sandbox/javaextend.js10
-rw-r--r--test/script/sandbox/jsadapter.js8
-rw-r--r--test/script/sandbox/loadLibrary.js8
-rw-r--r--test/script/sandbox/loadcompat.js8
-rw-r--r--test/script/sandbox/nashorninternals.js10
-rw-r--r--test/script/sandbox/net.js8
-rw-r--r--test/script/sandbox/property.js8
-rw-r--r--test/script/sandbox/reflection.js10
-rw-r--r--test/script/sandbox/runnable.js8
-rw-r--r--test/script/sandbox/unsafe.js10
-rw-r--r--test/script/test262.js8
-rw-r--r--test/script/test262_single.js8
-rw-r--r--test/script/trusted/JDK-8006424.js8
-rw-r--r--test/script/trusted/JDK-8006529.js59
-rw-r--r--test/script/trusted/JDK-8008305.js8
-rw-r--r--test/script/trusted/JDK-8008305_subtest.js8
-rw-r--r--test/script/trusted/JDK-8020809.js10
-rw-r--r--test/script/trusted/JDK-8021129.js10
-rw-r--r--test/script/trusted/JDK-8021189.js10
-rw-r--r--test/script/trusted/JDK-8025629.js8
-rw-r--r--test/script/trusted/JDK-8032060.js8
-rw-r--r--test/script/trusted/NASHORN-638.js8
-rw-r--r--test/script/trusted/NASHORN-653.js20
-rw-r--r--test/script/trusted/classfilter.js72
-rw-r--r--test/script/trusted/classfilter.js.EXPECTED11
-rw-r--r--test/script/trusted/classfilter_extends.js53
-rw-r--r--test/script/trusted/classfilter_extends.js.EXPECTED16
-rw-r--r--test/script/trusted/classfilter_mozilla_compat.js52
-rw-r--r--test/script/trusted/classfilter_mozilla_compat.js.EXPECTED12
-rw-r--r--test/script/trusted/event_queue.js123
-rw-r--r--test/script/trusted/event_queue.js.EXPECTED38
-rw-r--r--test/script/trusted/getenv.js8
-rw-r--r--test/script/trusted/optimistic_recompilation.js83
-rw-r--r--test/script/trusted/optimistic_recompilation.js.EXPECTED27
-rw-r--r--test/src/UnnamedPackageTestCallback.java8
-rw-r--r--test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java37
-rw-r--r--test/src/jdk/nashorn/api/NashornSQLDriver.java15
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java38
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java2
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java8
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java2
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java30
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java42
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java2
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/Person.java1
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/SharedObject.java29
-rw-r--r--test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java2
-rw-r--r--test/src/jdk/nashorn/api/scripting/InvocableTest.java49
-rw-r--r--test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java2
-rw-r--r--test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java35
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScopeTest.java170
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java113
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java104
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java93
-rw-r--r--test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java1
-rw-r--r--test/src/jdk/nashorn/api/scripting/Window.java1
-rw-r--r--test/src/jdk/nashorn/api/scripting/WindowEventHandler.java3
-rw-r--r--test/src/jdk/nashorn/internal/codegen/CompilerTest.java19
-rw-r--r--test/src/jdk/nashorn/internal/parser/ParserTest.java25
-rw-r--r--test/src/jdk/nashorn/internal/performance/AuroraWrapper.java1
-rw-r--r--test/src/jdk/nashorn/internal/performance/OctaneTest.java28
-rw-r--r--test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java9
-rw-r--r--test/src/jdk/nashorn/internal/performance/SplayTest.java5
-rw-r--r--test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java185
-rw-r--r--test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java111
-rw-r--r--test/src/jdk/nashorn/internal/runtime/ConsStringTest.java131
-rw-r--r--test/src/jdk/nashorn/internal/runtime/ContextTest.java28
-rw-r--r--test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java77
-rw-r--r--test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java212
-rw-r--r--test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java29
-rw-r--r--test/src/jdk/nashorn/internal/runtime/SourceTest.java22
-rw-r--r--test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java148
-rw-r--r--test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java5
-rw-r--r--test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java4
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java10
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java2
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java1
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java21
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java17
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/ScriptTest.java5
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java18
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/TestConfig.java1
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/TestFinder.java82
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/TestHelper.java4
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java7
-rw-r--r--test/src/jdk/nashorn/internal/test/models/InternalRunnable.java1
-rw-r--r--test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java2
-rw-r--r--test/src/jdk/nashorn/test/models/ClassLoaderAware.java32
-rw-r--r--test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java3
-rw-r--r--test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java2
-rw-r--r--test/src/jdk/nashorn/test/models/ConstructorWithArgument.java3
-rw-r--r--test/src/jdk/nashorn/test/models/DessertTopping.java1
-rw-r--r--test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java5
-rw-r--r--test/src/jdk/nashorn/test/models/FinalClass.java1
-rw-r--r--test/src/jdk/nashorn/test/models/FloorWax.java1
-rw-r--r--test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java5
-rw-r--r--test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java3
-rw-r--r--test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java9
-rw-r--r--test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java15
-rw-r--r--test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java1
-rw-r--r--test/src/jdk/nashorn/test/models/NullProvider.java34
-rw-r--r--test/src/jdk/nashorn/test/models/OuterClass.java14
-rw-r--r--test/src/jdk/nashorn/test/models/OverloadedSam.java1
-rw-r--r--test/src/jdk/nashorn/test/models/OverrideObject.java3
-rw-r--r--test/src/jdk/nashorn/test/models/PropertyBind.java11
-rw-r--r--test/src/jdk/nashorn/test/models/SourceHelper.java1
-rw-r--r--test/src/jdk/nashorn/test/models/StringArgs.java5
-rw-r--r--test/src/jdk/nashorn/test/models/Toothpaste.java1
-rw-r--r--test/src/jdk/nashorn/test/models/VarArgConstructor.java5
-rw-r--r--test/src/jdk/nashorn/test/tools/StaticTypeInspector.java55
1872 files changed, 66323 insertions, 24786 deletions
diff --git a/.hgtags b/.hgtags
index 9b1b564a..34734121 100644
--- a/.hgtags
+++ b/.hgtags
@@ -338,3 +338,25 @@ c68ba913a0eeea6eb94d9568e9985505ec3408a3 jdk8u31-b10
599bd596fa549d882aa8fc5104c322a75a3af728 jdk8u31-b11
f36c71a03e4ed467f630cc46d076a5bb4c58b6d5 jdk8u31-b12
ec36fa3b35eb00f053d624ae837579c6b8e446ac jdk8u31-b13
+f2925491b61b22ac42f8c30ee9c6723ffa401a4c jdk8u40-b00
+62468d841b842769d875bd97d10370585c296eb7 jdk8u40-b01
+b476c69c820ac1e05071f4de5abab8e2dff80e87 jdk8u40-b02
+a2e0a985764b5afd5f316429bfab4f44bf150f7f jdk8u40-b03
+34c17c95665419ed76a98f5cf1210ed58eb2eca3 jdk8u40-b04
+2d75c391f61f31538b4c3dcc9778fc6742125ec4 jdk8u40-b05
+1196f17cf7bc709766319f5bf7a5394a7251b47a jdk8u40-b06
+0032961e1866c22afe3d0bbbb217f8840be61846 jdk8u40-b07
+89551828b279233825204b72233edafc72d8feb3 jdk8u40-b08
+6a8ecdeae4a9a438eed637b5a5d0d18fddb9f711 jdk8u40-b09
+076b1f38a5ccd4692a6f93939a7fc03bc1a1bbb4 jdk8u40-b10
+57c7b273277e00f7a98fafb18ff07aa3245808f0 jdk8u40-b11
+375a3a3256d041fe7334638a95e69b4c11d6104b jdk8u40-b12
+d60fbb5343c186abbf92b0259e67efb3b71377b4 jdk8u40-b13
+7e34104c55cafa0b579be3a480dda383c616a378 jdk8u40-b14
+fc37699ddc0ed41d4ab5da821211a6d2648c8883 jdk8u40-b15
+e079f3f6d536510b1ab3589b1038d893d78302ac jdk8u40-b16
+88e22262fdb26e3154a1034c2413415e97b9a86a jdk8u40-b17
+653739706172ae94e999731a3a9f10f8ce11ffca jdk8u40-b18
+6ec61d2494283fbaca6df227f1a5b45487dc1ca7 jdk8u40-b19
+05a3614ed5276e5db2a73cce918be04b1a2922fb jdk8u45-b00
+21ec16eb7e6346c78b4fa67ccd6d2a9c58f0b696 jdk8u45-b01
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index 6d1c60f2..c34ce6b3 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -3385,7 +3385,7 @@ with JRE 8, JDK 8, and OpenJDK 8.
included with JRE 8, JDK 8, and OpenJDK 8.
Apache Commons Math 3.2
- Apache Derby 10.10.1.3
+ Apache Derby 10.11.1.2
Apache Jakarta BCEL 5.1
Apache Jakarta Regexp 1.4
Apache Santuario XML Security for Java 1.5.4
diff --git a/bin/checkintest.sh b/bin/checkintest.sh
deleted file mode 100644
index c4a9e96c..00000000
--- a/bin/checkintest.sh
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#best pass rate at test 262 known
-TEST262_PASS_AT_LEAST=435
-
-RUN_TEST="true"
-RUN_TEST262="true"
-RUN_NODE="true"
-KEEP_OUTPUT="true"
-CLEAN_AND_BUILD_NASHORN="true"
-
-#the stable node version to sync against
-NODE_LAST_STABLE=v0.6.18
-
-#parse args
-for arg in $*
-do
- if [ $arg = "--no-test" ]; then
- RUN_TEST="false"
- echo "**** WARNING - you have disabled 'ant test', which is a minimum checkin requirement..."
- elif [ $arg = "--no-262" ]; then
- RUN_TEST262="false"
- elif [ $arg = "--no-node" ]; then
- RUN_NODE="false"
- elif [ $arg = "--no-build" ]; then
- CLEAN_AND_BUILD_NASHORN="false"
- elif [ $arg = "--no-logs" ]; then
- KEEP_OUTPUT="false"
- fi
-done
-
-function lastpart() {
- arr=$(echo $1 | tr "/" "\n")
- for x in $arr
- do
- _last=$x
- done
- echo $_last
-}
-
-function check_installed() {
- which $1 >/dev/null
- if [ $? -ne 0 ]; then
- echo "Error $1 not installed: $?"
- exit 2
- fi
-}
-
-check_installed hg
-check_installed git
-check_installed mv
-check_installed git
-
-PWD=$(pwd);
-
-while [ -z $NASHORN_ROOT ]
-do
- if [ -e $PWD/.hg ]; then
- NASHORN_ROOT=${PWD}
- break
- fi
- PWD=$(dirname ${PWD})
-done
-
-echo "Nashorn root detected at ${NASHORN_ROOT}"
-
-COMMON_ROOT=$(dirname $NASHORN_ROOT)
-echo "Common root is ${COMMON_ROOT}"
-
-echo "Running checkintest..."
-
-ABSOLUTE_NASHORN_HOME=$COMMON_ROOT/$(lastpart $NASHORN_ROOT)
-
-if [ $CLEAN_AND_BUILD_NASHORN != "false" ]; then
- echo "Cleaning and building nashorn at $ABSOLUTE_NASHORN_HOME/nashorn..."
- $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant clean >/dev/null 2>/dev/null)
- $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant jar >/dev/null 2>/dev/null)
- echo "Done."
-fi
-
-function failure_check() {
- while read line
- do
- LINE=$(echo $line | grep "Tests run")
- if [ "${LINE}" != "" ]; then
- RESULT=$(echo $line | grep "Failures: 0" | grep "Errors: 0")
- if [ "${RESULT}" == "" ]; then
- TESTNAME=$2
- echo "There were errors in ${TESTNAME} : ${LINE}"
- exit 1
- fi
- fi
- done < $1
-}
-
-function test() {
- TEST_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
- echo "Running 'ant test' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..."
- $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test >$TEST_OUTPUT)
- echo "Done."
-
- failure_check $TEST_OUTPUT
-
- echo "**** SUCCESS: 'ant test' successful"
-
- if [ $KEEP_OUTPUT == "true" ]; then
- cp $TEST_OUTPUT ./checkintest.test.log
- rm -fr $TEST_OUTPUT
- fi
-}
-
-if [ $RUN_TEST != "false" ]; then
- test;
-fi
-
-function test262() {
-
- echo "Running 'ant test262parallel' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..."
- TEST262_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
-
- echo "Looking for ${ABSOLUTE_NASHORN_HOME}/test/test262..."
-
- if [ ! -e $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 ]; then
- echo "test262 is missing... looking in $COMMON_ROOT..."
- if [ ! -e $COMMON_ROOT/test262 ]; then
- echo "... not there either... cloning from repo..."
- hg clone http://hg.ecmascript.org/tests/test262 $COMMON_ROOT/test262 >/dev/null 2>/dev/null
- echo "Done."
- fi
- echo "Adding soft link ${COMMON_ROOT}/test262 -> ${ABSOLUTE_NASHORN_HOME}/test/test262..."
- ln -s $COMMON_ROOT/test262 $ABSOLUTE_NASHORN_HOME/nashorn/test/test262
- echo "Done."
- fi
-
- echo "Ensuring test262 is up to date..."
- $(cd $ABSOLUTE_NASHORN_HOME/nashorn/test/test262; hg pull -u >/dev/null 2>/dev/null)
- echo "Done."
-
- echo "Running test262..."
- $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test262parallel > $TEST262_OUTPUT)
-
- FAILED=$(cat $TEST262_OUTPUT|grep "Tests run:"| cut -d ' ' -f 15 |tr -cd '"[[:digit:]]')
- if [ $FAILED -gt $TEST262_PASS_AT_LEAST ]; then
- echo "FAILURE: There are ${FAILED} failures in test262 and can be no more than ${TEST262_PASS_AT_LEAST}"
- cp $TEST262_OUTPUT ./checkintest.test262.log
- echo "See ./checkintest.test262.log"
- echo "Terminating due to error"
- exit 1
- elif [ $FAILED -lt $TEST262_PASS_AT_LEAST ]; then
- echo "There seem to have been fixes to 262. ${FAILED} < ${TEST262_PASS_AT_LEAST}. Please update limit in bin/checkintest.sh"
- fi
-
- echo "**** SUCCESS: Test262 passed with no more than ${TEST262_PASS_AT_LEAST} failures."
-
- if [ $KEEP_OUTPUT == "true" ]; then
- cp $TEST262_OUTPUT ./checkintest.test262.log
- rm -fr $TEST262_OUTPUT
- fi
-}
-
-if [ $RUN_TEST262 != "false" ]; then
- test262;
-fi;
-
-function testnode() {
- TESTNODEJAR_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
-
- echo "Running node tests..."
-#replace node jar properties nashorn with this nashorn
-
- NODEJAR_PROPERTIES=~/nodejar.properties
-
- NODE_HOME=$(cat $NODEJAR_PROPERTIES | grep ^node.home | cut -f2 -d=)
- NASHORN_HOME=$(cat $NODEJAR_PROPERTIES | grep ^nashorn.home | cut -f2 -d=)
-
- ABSOLUTE_NODE_HOME=$COMMON_ROOT/$(lastpart $NODE_HOME)
-
- echo "Writing nodejar.properties..."
-
- cat > $NODEJAR_PROPERTIES << EOF
-node.home=../node
-nashorn.home=../$(lastpart $NASHORN_ROOT)
-EOF
- echo "Done."
- echo "Checking node home ${ABSOLUTE_NODE_HOME}..."
-
- if [ ! -e $ABSOLUTE_NODE_HOME ]; then
- echo "Node base dir not found. Cloning node..."
- $(cd $COMMON_ROOT; git clone https://github.com/joyent/node.git $(lastpart $NODE_HOME) >/dev/null 2>/dev/null)
- echo "Done."
- echo "Updating to last stable version ${NODE_LAST_STABLE}..."
- $(cd $ABSOLUTE_NODE_HOME; git checkout $NODE_LAST_STABLE >/dev/null 2>/dev/null)
- echo "Done."
- echo "Running configure..."
- $(cd $ABSOLUTE_NODE_HOME; ./configure >/dev/null 2>/dev/null)
- echo "Done."
- fi
-
- echo "Ensuring node is built..."
-#make sure node is built
- $(cd $ABSOLUTE_NODE_HOME; make >/dev/null 2>/dev/null)
- echo "Done."
-
- NODEJAR_HOME=$COMMON_ROOT/nodejar
-
- if [ ! -e $NODEJAR_HOME ]; then
- echo "No node jar home found. cloning from depot..."
- $(cd $COMMON_ROOT; hg clone https://hg.kenai.com/hg/nodejs~source nodejar >/dev/null 2>/dev/null)
- $(cd $COMMON_ROOT/nodejar; ant >/dev/null)
- echo "Done."
- echo "Copying node files..."
- $(cd $COMMON_ROOT/nodejar; ant copy-node-files >/dev/null 2>/dev/null)
- echo "Patching node files..."
- $(cd $COMMON_ROOT/nodejar; ant patch-node-files >/dev/null 2>/dev/null)
- echo "Done."
- fi
-
- echo "Ensuring node.jar is up to date from source depot..."
- $(cd $COMMON_ROOT/nodejar; hg pull -u >/dev/null 2>/dev/null)
- echo "Done."
-
- echo "Installing nashorn..."
- $(cd $COMMON_ROOT/nodejar; ant >/dev/null)
- echo "Done."
-
- echo "Running node.jar test..."
- $(cd $COMMON_ROOT/nodejar; mvn clean verify >$TESTNODEJAR_OUTPUT)
- echo "Done."
-
- failure_check $TESTNODEJAR_OUTPUT
-
- echo "**** SUCCESS: Node test successful."
-
- if [ $KEEP_OUTPUT == "true" ]; then
- rm -fr $TESTNODEJAR_OUTPUT
- cp $TESTNODEJAR_OUTPUT ./checkintest.nodejar.log
- fi
-}
-
-if [ $RUN_NODE != "false" ]; then
- testnode;
-fi;
-
-echo "Finished"
diff --git a/bin/dump_octane_code.sh b/bin/dump_octane_code.sh
deleted file mode 100644
index d24ab2ce..00000000
--- a/bin/dump_octane_code.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#
-# The purpose of this script is to provide a large amount of IR/bytecode from a known
-# application to be diffed against the same output with a different Nashorn version.
-# That way we can quickly detect if a seemingly minute change modifies a lot of code,
-# which it most likely shouldn't. One example of this was when AccessSpecializer was
-# moved into Lower the first time, it worked fine, but as a lot of Scope information
-# at the time was finalized further down the code pipeline it did a lot fewer callsite
-# specializations. This would have been immediately detected with a before and after
-# diff using the output from this script.
-#
-
-ITERS=$1
-if [ -z $ITERS ]; then
- ITERS=7
-fi
-NASHORN_JAR=dist/nashorn.jar
-JVM_FLAGS="-ea -esa -server -jar ${NASHORN_JAR}"
-
-BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "mandreel.js" "navier-stokes.js" "pdfjs.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" )
-
-for BENCHMARK in "${BENCHMARKS[@]}"
-do
- echo "START: ${BENCHMARK}"
- CMD="${JAVA_HOME}/bin/java ${JVM_FLAGS} -co --print-lower-parse test/script/external/octane/${BENCHMARK}"
- $CMD
- echo "END: ${BENCHMARK}"
- echo ""
-done
-
-echo "Done"
diff --git a/bin/fixorphantests.sh b/bin/fixorphantests.sh
deleted file mode 100644
index 604e2da0..00000000
--- a/bin/fixorphantests.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#ensure that all tests tagged with @test are also tagged with @run
-
-for f in $(find test/script/basic/*.js); do
- grep @test $f >/dev/null
- TEST=$?
- grep @run $f >/dev/null
- RUN=$?
-
- if [ $TEST -eq 0 ] && [ ! $RUN -eq 0 ]; then
- echo "repairing ${f}..."
- TEMP=$(mktemp /tmp/scratch.XXXXXX)
-
- #IFS='', -raw flag to preserve white space
- while IFS='' read -r line; do
- echo $line | grep @test >/dev/null
- TEST=$?
- printf "%s\n" "$line"
- if [ $TEST -eq 0 ]; then
- printf "%s\n" "$line" | sed s/@test/@run/g
- fi
- done < $f >$TEMP
-
- cp $TEMP $f
-
- rm -fr $TEMP
- fi
-
-done
diff --git a/bin/fixwhitespace.sh b/bin/fixwhitespace.sh
index cac757db..d3274700 100644
--- a/bin/fixwhitespace.sh
+++ b/bin/fixwhitespace.sh
@@ -22,9 +22,16 @@
# questions.
#
-#convert tabs to spaces
-find . -name "*.java" -exec sed -i "" 's/ / /g' {} \;
-
-#remove trailing whitespace
-find . -name "*.java" -exec sed -i "" 's/[ ]*$//' \{} \;
+fix() {
+ #convert tabs to spaces
+ find . -name $1 -exec sed -i "" 's/ / /g' {} \;
+ #remove trailing whitespace
+ find . -name $1 -exec sed -i "" 's/[ ]*$//' \{} \;
+}
+if [ ! -z $1 ]; then
+ fix $1;
+else
+ fix "*.java"
+ fix "*.js"
+fi
diff --git a/bin/jjs.bat b/bin/jjs.bat
deleted file mode 100644
index 3c1c1595..00000000
--- a/bin/jjs.bat
+++ /dev/null
@@ -1,27 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation. Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-rem
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false jdk.nashorn.tools.Shell
diff --git a/bin/jjssecure b/bin/jjssecure
deleted file mode 100644
index db6bdfc4..00000000
--- a/bin/jjssecure
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $*
diff --git a/bin/jjssecure.bat b/bin/jjssecure.bat
deleted file mode 100644
index f8da10aa..00000000
--- a/bin/jjssecure.bat
+++ /dev/null
@@ -1,27 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation. Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-rem
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=%~dp0\..\make\java.security.override -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.home=%~dp0\.. -Djava.security.manager jdk.nashorn.tools.Shell
diff --git a/bin/nashorn b/bin/nashorn
deleted file mode 100644
index da22be1f..00000000
--- a/bin/nashorn
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
diff --git a/bin/nashorn.bat b/bin/nashorn.bat
deleted file mode 100644
index 2961ac69..00000000
--- a/bin/nashorn.bat
+++ /dev/null
@@ -1,27 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation. Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-rem
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=%~dp0\..\dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Dnashorn.debug=true -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -l nashorn
diff --git a/bin/nashornsecure b/bin/nashornsecure
deleted file mode 100644
index 77c7c529..00000000
--- a/bin/nashornsecure
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
diff --git a/bin/nashornsecure.bat b/bin/nashornsecure.bat
deleted file mode 100644
index 5a4eca63..00000000
--- a/bin/nashornsecure.bat
+++ /dev/null
@@ -1,27 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation. Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-rem
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-jrunscript -J-Djava.security.properties=%~dp0\..\make\java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=%~dp0\..\dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Dnashorn.debug=true -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -l nashorn
diff --git a/bin/rm-non-tracked.sh b/bin/rm-non-tracked.sh
deleted file mode 100644
index 1eac1996..00000000
--- a/bin/rm-non-tracked.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-hg status|grep ^\?|awk '{print $2}'|xargs rm
diff --git a/bin/runopt.sh b/bin/runopt.sh
new file mode 100644
index 00000000..5ec9046b
--- /dev/null
+++ b/bin/runopt.sh
@@ -0,0 +1,136 @@
+#!/bin/sh
+#
+# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+###########################################################################################
+# This is a helper script to evaluate nashorn with optimistic types
+# it produces a flight recording for every run, and uses the best
+# known flags for performance for the current configration
+###########################################################################################
+
+# Flags to enable assertions, we need the system assertions too, since
+# this script runs Nashorn in the BCP to override any nashorn.jar that might
+# reside in your $JAVA_HOME/jre/lib/ext/nashorn.jar
+#
+ENABLE_ASSERTIONS_FLAGS="-ea -esa"
+
+# Flags to instrument lambdaform computation, caching, interpretation and compilation
+# Default compile threshold for lambdaforms is 30
+#
+#LAMBDAFORM_FLAGS="\
+# -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 \
+# -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true \
+# -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true \
+# -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
+
+# Flags to run trusted tests from the Nashorn test suite
+#
+#TRUSTED_TEST_FLAGS="\
+#-Djava.security.manager \
+#-Djava.security.policy=../build/nashorn.policy -Dnashorn.debug"
+
+# Testing out new code optimizations using the generic hotspot "new code" parameter
+#
+#USE_NEW_CODE_FLAGS=-XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode
+
+#
+#-Dnashorn.typeInfo.disabled=false \
+# and for Nashorn options:
+# --class-cache-size=0 --persistent-code-cache=false
+
+# Unique timestamped file name for JFR recordings. For JFR, we also have to
+# crank up the stack cutoff depth to 1024, because of ridiculously long lambda form
+# stack traces.
+#
+# It is also recommended that you go into $JAVA_HOME/jre/lib/jfr/default.jfc and
+# set the "method-sampling-interval" Normal and Maximum sample time as low as you
+# can go (10 ms on most platforms). The default is normally higher. The increased
+# sampling overhead is usually negligible for Nashorn runs, but the data is better
+
+if [ -z $JFR_FILENAME ]; then
+ JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
+fi
+
+# Flight recorder
+#
+# see above - already in place, copy the flags down here to disable
+ENABLE_FLIGHT_RECORDER_FLAGS="\
+ -XX:+UnlockCommercialFeatures \
+ -XX:+FlightRecorder \
+ -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024"
+
+# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine,
+# keeping this flag around for experimental reasons. Replace + with - to switch it off
+#
+#ENABLE_TYPE_SPECIALIZATION_FLAGS=-XX:+UseTypeSpeculation
+
+# Same with math intrinsics. They should be enabled by default in 8u20 and 9, so
+# this disables them if needed
+#
+#DISABLE_MATH_INTRINSICS_FLAGS=-XX:-UseMathExactIntrinsics
+
+# Add timing to time the compilation phases.
+#ENABLE_TIME_FLAGS=--log=time
+
+# Add ShowHiddenFrames to get lambda form internals on the stack traces
+#ENABLE_SHOW_HIDDEN_FRAMES_FLAGS=-XX:+ShowHiddenFrames
+
+# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product,
+# That tired compilation is switched off, for C2 only output and that the number of
+# compiler threads is set to 1 for determinsm.
+#
+#PRINT_ASM_FLAGS=-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \
+
+# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments)
+#TIER_COMPILATION_THRESHOLD_FLAGS=-XX:IncreaseFirstTierCompileThresholdAt=10
+
+# Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming
+# that we run the script from the make dir
+DIR=..
+NASHORN_JAR=$DIR/dist/nashorn.jar
+
+
+# The built Nashorn jar is placed first in the bootclasspath to override the JDK
+# nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in
+# nashorn count as system assertions in this configuration
+
+# Type profiling default level is 111, 222 adds some compile time, but is faster
+
+$JAVA_HOME/bin/java \
+$ENABLE_ASSERTIONS_FLAGS \
+$LAMBDAFORM_FLAGS \
+$TRUSTED_FLAGS \
+$USE_NEW_CODE_FLAGS \
+$ENABLE_SHOW_HIDDEN_FRAMES_FLAGS \
+$ENABLE_FLIGHT_RECORDER_FLAGS \
+$ENABLE_TYPE_SPECIALIZATION_FLAGS \
+$TIERED_COMPILATION_THRESOLD_FLAGS \
+$DISABLE_MATH_INTRINSICS_FLAGS \
+$PRINT_ASM_FLAGS \
+-Xbootclasspath/p:$NASHORN_JAR \
+-Xms2G -Xmx2G \
+-XX:TypeProfileLevel=222 \
+-cp $CLASSPATH:../build/test/classes/ \
+jdk.nashorn.tools.Shell $ENABLE_TIME_FLAGS ${@}
+
+
diff --git a/bin/verbose_octane.bat b/bin/verbose_octane.bat
deleted file mode 100644
index ab9e4846..00000000
--- a/bin/verbose_octane.bat
+++ /dev/null
@@ -1,59 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation.
-rem
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-if "%JAVA_HOME%" neq "" (
- call :run "%JAVA_HOME%/bin/java"
-) else (
- call :run java
-)
-goto :EOF
-
-:run
-setlocal
-set NASHORN_JAR=dist/nashorn.jar
-set JVM_FLAGS=-Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -jar %NASHORN_JAR%
-set JVM_FLAGS7=-Xbootclasspath/p:%NASHORN_JAR% %JVM_FLAGS%
-set OCTANE_ARGS=--verbose --iterations 7
-
-%1 -fullversion 2>&1 | findstr /L /C:"version ""1.7"
-if %errorlevel% equ 0 (
- set CMD=%1 %JVM_FLAGS7%
-) else (
- %1 -fullversion
- set CMD=%1 %JVM_FLAGS%
-)
-
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/box2d.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/code-load.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/crypto.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/deltablue.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/gbemu.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/navier-stokes.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/pdfjs.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/raytrace.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/regexp.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/richards.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/splay.js %OCTANE_ARGS%
-endlocal
-goto :EOF
diff --git a/bin/verbose_octane.sh b/bin/verbose_octane.sh
deleted file mode 100644
index 1895afed..00000000
--- a/bin/verbose_octane.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-ITERS=$1
-if [ -z $ITERS ]; then
- ITERS=7
-fi
-NASHORN_JAR=dist/nashorn.jar
-JVM_FLAGS="-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+UnlockDiagnosticVMOptions -Dnashorn.unstable.relink.threshold=8 -Xms2G -Xmx2G -XX:+TieredCompilation -server -jar ${NASHORN_JAR}"
-JVM_FLAGS7="-Xbootclasspath/p:${NASHORN_JAR} ${JVM_FLAGS}"
-OCTANE_ARGS="--verbose --iterations ${ITERS}"
-
-BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "navier-stokes.js" "pdfjs.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" )
-# TODO mandreel.js has metaspace issues
-
-if [ ! -z $JAVA7_HOME ]; then
- echo "running ${ITERS} iterations with java7 using JAVA_HOME=${JAVA7_HOME}..."
- for BENCHMARK in "${BENCHMARKS[@]}"
- do
- CMD="${JAVA7_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}"
- $CMD
- done
-else
- echo "no JAVA7_HOME set. skipping java7"
-fi
-
-if [ ! -z $JAVA8_HOME ]; then
- echo "running ${ITERS} iterations with java8 using JAVA_HOME=${JAVA8_HOME}..."
- for BENCHMARK in "${BENCHMARKS[@]}"
- do
- CMD="${JAVA8_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}"
- $CMD
- done
-else
- echo "no JAVA8_HOME set."
-fi
-
-echo "Done"
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index bb6abbc0..75874316 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -31,29 +31,29 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.GETTER_PREFIX;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.LIST_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC;
@@ -292,7 +292,6 @@ public class ClassGenerator {
mi.push(memInfo.getArity());
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC);
}
-
}
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
index 67cbde44..2661e096 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
@@ -32,9 +32,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFFIX;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index e47f8b16..cc3524da 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -28,7 +28,6 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DES
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC;
-
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.nashorn.internal.objects.annotations.Where;
@@ -75,10 +74,6 @@ public final class MemberInfo implements Cloneable {
* This is a specialized version of a function
*/
SPECIALIZED_FUNCTION,
- /**
- * This is a specialized version of a constructor
- */
- SPECIALIZED_CONSTRUCTOR
}
// keep in sync with jdk.nashorn.internal.objects.annotations.Attribute
@@ -107,6 +102,12 @@ public final class MemberInfo implements Cloneable {
private Where where;
+ private Type linkLogicClass;
+
+ private boolean isSpecializedConstructor;
+
+ private boolean isOptimistic;
+
/**
* @return the kind
*/
@@ -136,6 +137,57 @@ public final class MemberInfo implements Cloneable {
}
/**
+ * Tag something as specialized constructor or not
+ * @param isSpecializedConstructor boolean, true if specialized constructor
+ */
+ public void setIsSpecializedConstructor(final boolean isSpecializedConstructor) {
+ this.isSpecializedConstructor = isSpecializedConstructor;
+ }
+
+ /**
+ * Check if something is a specialized constructor
+ * @return true if specialized constructor
+ */
+ public boolean isSpecializedConstructor() {
+ return isSpecializedConstructor;
+ }
+
+ /**
+ * Check if this is an optimistic builtin function
+ * @return true if optimistic builtin
+ */
+ public boolean isOptimistic() {
+ return isOptimistic;
+ }
+
+ /**
+ * Tag something as optimitic builtin or not
+ * @param isOptimistic boolean, true if builtin constructor
+ */
+ public void setIsOptimistic(final boolean isOptimistic) {
+ this.isOptimistic = isOptimistic;
+ }
+
+ /**
+ * Get the SpecializedFunction guard for specializations, i.e. optimistic
+ * builtins
+ * @return specialization, null if none
+ */
+ public Type getLinkLogicClass() {
+ return linkLogicClass;
+ }
+
+ /**
+ * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic
+ * builtins
+ * @param linkLogicClass link logic class
+ */
+
+ public void setLinkLogicClass(final Type linkLogicClass) {
+ this.linkLogicClass = linkLogicClass;
+ }
+
+ /**
* @return the attributes
*/
public int getAttributes() {
@@ -304,22 +356,9 @@ public final class MemberInfo implements Cloneable {
}
}
break;
- case SPECIALIZED_CONSTRUCTOR: {
- final Type returnType = Type.getReturnType(javaDesc);
- if (!isJSObjectType(returnType)) {
- error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType);
- }
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- for (int i = 0; i < argTypes.length; i++) {
- if (!isValidJSType(argTypes[i])) {
- error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]);
- }
- }
- }
- break;
case FUNCTION: {
final Type returnType = Type.getReturnType(javaDesc);
- if (!isValidJSType(returnType)) {
+ if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) {
error("return value of a @Function method should be a valid JS type, found " + returnType);
}
final Type[] argTypes = Type.getArgumentTypes(javaDesc);
@@ -351,7 +390,7 @@ public final class MemberInfo implements Cloneable {
break;
case SPECIALIZED_FUNCTION: {
final Type returnType = Type.getReturnType(javaDesc);
- if (!isValidJSType(returnType)) {
+ if (!(isValidJSType(returnType) || (isSpecializedConstructor() && Type.VOID_TYPE == returnType))) {
error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType);
}
final Type[] argTypes = Type.getArgumentTypes(javaDesc);
@@ -371,9 +410,8 @@ public final class MemberInfo implements Cloneable {
error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]);
}
- final Type returnType = Type.getReturnType(javaDesc);
- if (!isJavaLangObject(returnType)) {
- error("return type of a @Getter method should be Object, found: " + javaDesc);
+ if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
+ error("return type of getter should not be void");
}
}
break;
@@ -413,6 +451,10 @@ public final class MemberInfo implements Cloneable {
}
}
}
+ break;
+
+ default:
+ break;
}
}
@@ -451,7 +493,7 @@ public final class MemberInfo implements Cloneable {
if (type.getSort() == Type.OBJECT) {
try {
- final Class clazz = Class.forName(type.getClassName(), false, myLoader);
+ final Class<?> clazz = Class.forName(type.getClassName(), false, myLoader);
return ScriptObject.class.isAssignableFrom(clazz);
} catch (final ClassNotFoundException cnfe) {
return false;
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
index 479d1d31..a8bd954f 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
@@ -56,6 +56,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
+import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
@@ -76,13 +77,16 @@ import static jdk.internal.org.objectweb.asm.Opcodes.SALOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.SASTORE;
import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
import static jdk.internal.org.objectweb.asm.Opcodes.SWAP;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.METHODHANDLE_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_METHODHANDLE;
-
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT2;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT3;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SPECIALIZATION;
import java.util.List;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Type;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
/**
* Base class for all method generating classes.
@@ -95,6 +99,8 @@ public class MethodGenerator extends MethodVisitor {
private final Type returnType;
private final Type[] argumentTypes;
+ static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType(LinkLogic.getEmptyLinkLogicClass());
+
MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) {
super(ASM4, mv);
this.access = access;
@@ -380,6 +386,11 @@ public class MethodGenerator extends MethodVisitor {
super.visitFieldInsn(GETFIELD, owner, field, desc);
}
+ private static boolean linkLogicIsEmpty(final Type type) {
+ assert EMPTY_LINK_LOGIC_TYPE != null; //type is ok for null if we are a @SpecializedFunction without any attribs
+ return EMPTY_LINK_LOGIC_TYPE.equals(type);
+ }
+
void memberInfoArray(final String className, final List<MemberInfo> mis) {
if (mis.isEmpty()) {
pushNull();
@@ -388,12 +399,22 @@ public class MethodGenerator extends MethodVisitor {
int pos = 0;
push(mis.size());
- newObjectArray(METHODHANDLE_TYPE);
+ newObjectArray(SPECIALIZATION_TYPE);
for (final MemberInfo mi : mis) {
dup();
push(pos++);
+ visitTypeInsn(NEW, SPECIALIZATION_TYPE);
+ dup();
visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc()));
- arrayStore(TYPE_METHODHANDLE);
+ final Type linkLogicClass = mi.getLinkLogicClass();
+ final boolean linkLogic = !linkLogicIsEmpty(linkLogicClass);
+ final String ctor = linkLogic ? SPECIALIZATION_INIT3 : SPECIALIZATION_INIT2;
+ if (linkLogic) {
+ visitLdcInsn(linkLogicClass);
+ }
+ visitInsn(mi.isOptimistic() ? ICONST_1 : ICONST_0);
+ visitMethodInsn(INVOKESPECIAL, SPECIALIZATION_TYPE, INIT, ctor, false);
+ arrayStore(TYPE_SPECIALIZATION);
}
}
@@ -413,7 +434,8 @@ public class MethodGenerator extends MethodVisitor {
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/String;)V", false);
+ "(Ljava/lang/String;)V",
+ false);
}
// print the object on the top of the stack
@@ -426,6 +448,7 @@ public class MethodGenerator extends MethodVisitor {
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/Object;)V", false);
+ "(Ljava/lang/Object;)V",
+ false);
}
}
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
index 7b1fff76..8eb19b7d 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
@@ -31,9 +31,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC;
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
index 0a1579ff..9e3dfc17 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
@@ -37,8 +37,8 @@ import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Setter;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
@@ -56,8 +56,8 @@ public final class ScriptClassInfo {
static final String SETTER_ANNO_DESC = Type.getDescriptor(Setter.class);
static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class);
static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class);
+ static final String LINK_LOGIC_DESC = Type.getDescriptor(LinkLogic.class);
static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class);
- static final String SPECIALIZED_CONSTRUCTOR = Type.getDescriptor(SpecializedConstructor.class);
static final Map<String, Kind> annotations = new HashMap<>();
@@ -69,7 +69,6 @@ public final class ScriptClassInfo {
annotations.put(SETTER_ANNO_DESC, Kind.SETTER);
annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY);
annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION);
- annotations.put(SPECIALIZED_CONSTRUCTOR, Kind.SPECIALIZED_CONSTRUCTOR);
}
// name of the script class
@@ -119,11 +118,12 @@ public final class ScriptClassInfo {
List<MemberInfo> getSpecializedConstructors() {
final List<MemberInfo> res = new LinkedList<>();
for (final MemberInfo memInfo : members) {
- if (memInfo.getKind() == Kind.SPECIALIZED_CONSTRUCTOR) {
+ if (memInfo.isSpecializedConstructor()) {
+ assert memInfo.getKind() == Kind.SPECIALIZED_FUNCTION;
res.add(memInfo);
}
}
- return res;
+ return Collections.unmodifiableList(res);
}
int getPrototypeMemberCount() {
@@ -175,7 +175,7 @@ public final class ScriptClassInfo {
res.add(memInfo);
}
}
- return res;
+ return Collections.unmodifiableList(res);
}
MemberInfo findSetter(final MemberInfo getter) {
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
index 5561cfbf..aa477621 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
@@ -27,7 +27,6 @@ package jdk.nashorn.internal.tools.nasgen;
import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.SCRIPT_CLASS_ANNO_DESC;
import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.WHERE_ENUM_DESC;
-
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
@@ -41,6 +40,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.Type;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
@@ -194,6 +194,7 @@ public class ScriptClassInfoCollector extends ClassVisitor {
final MemberInfo memInfo = new MemberInfo();
+ //annokind == e.g. GETTER or SPECIALIZED_FUNCTION
memInfo.setKind(annoKind);
memInfo.setJavaName(methodName);
memInfo.setJavaDesc(methodDesc);
@@ -208,12 +209,18 @@ public class ScriptClassInfoCollector extends ClassVisitor {
private Integer attributes;
private Integer arity;
private Where where;
+ private boolean isSpecializedConstructor;
+ private boolean isOptimistic;
+ private Type linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE;
@Override
public void visit(final String annotationName, final Object annotationValue) {
switch (annotationName) {
case "name":
this.name = (String)annotationValue;
+ if (name.isEmpty()) {
+ name = null;
+ }
break;
case "attributes":
this.attributes = (Integer)annotationValue;
@@ -221,6 +228,17 @@ public class ScriptClassInfoCollector extends ClassVisitor {
case "arity":
this.arity = (Integer)annotationValue;
break;
+ case "isConstructor":
+ assert annoKind == Kind.SPECIALIZED_FUNCTION;
+ this.isSpecializedConstructor = (Boolean)annotationValue;
+ break;
+ case "isOptimistic":
+ assert annoKind == Kind.SPECIALIZED_FUNCTION;
+ this.isOptimistic = (Boolean)annotationValue;
+ break;
+ case "linkLogic":
+ this.linkLogicClass = (Type)annotationValue;
+ break;
default:
break;
}
@@ -230,12 +248,19 @@ public class ScriptClassInfoCollector extends ClassVisitor {
@Override
public void visitEnum(final String enumName, final String desc, final String enumValue) {
- if ("where".equals(enumName) && WHERE_ENUM_DESC.equals(desc)) {
- this.where = Where.valueOf(enumValue);
+ switch (enumName) {
+ case "where":
+ if (WHERE_ENUM_DESC.equals(desc)) {
+ this.where = Where.valueOf(enumValue);
+ }
+ break;
+ default:
+ break;
}
super.visitEnum(enumName, desc, enumValue);
}
+ @SuppressWarnings("fallthrough")
@Override
public void visitEnd() {
super.visitEnd();
@@ -256,7 +281,6 @@ public class ScriptClassInfoCollector extends ClassVisitor {
case SETTER:
where = Where.INSTANCE;
break;
- case SPECIALIZED_CONSTRUCTOR:
case CONSTRUCTOR:
where = Where.CONSTRUCTOR;
break;
@@ -264,12 +288,18 @@ public class ScriptClassInfoCollector extends ClassVisitor {
where = Where.PROTOTYPE;
break;
case SPECIALIZED_FUNCTION:
- //TODO is this correct
+ if (isSpecializedConstructor) {
+ where = Where.CONSTRUCTOR;
+ }
+ //fallthru
default:
break;
}
}
memInfo.setWhere(where);
+ memInfo.setLinkLogicClass(linkLogicClass);
+ memInfo.setIsSpecializedConstructor(isSpecializedConstructor);
+ memInfo.setIsOptimistic(isOptimistic);
}
};
}
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
index 0ec233ae..0d6a9e37 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
@@ -38,7 +38,6 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DES
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE;
-
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index 1d724187..8656a42b 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -26,9 +26,8 @@
package jdk.nashorn.internal.tools.nasgen;
import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Method;
-import java.util.Collection;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import jdk.internal.org.objectweb.asm.Type;
@@ -38,6 +37,7 @@ import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.Specialization;
/**
* String constants used for code generation/instrumentation.
@@ -45,20 +45,26 @@ import jdk.nashorn.internal.runtime.ScriptObject;
@SuppressWarnings("javadoc")
public interface StringConstants {
// standard jdk types, methods
- static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class);
- static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
- static final Type TYPE_OBJECT = Type.getType(Object.class);
- static final Type TYPE_STRING = Type.getType(String.class);
- static final Type TYPE_COLLECTION = Type.getType(Collection.class);
- static final Type TYPE_COLLECTIONS = Type.getType(Collections.class);
- static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class);
- static final Type TYPE_LIST = Type.getType(List.class);
+ static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class);
+ static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
+ static final Type TYPE_SPECIALIZATION = Type.getType(Specialization.class);
+ static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType(Specialization[].class);
+ static final Type TYPE_OBJECT = Type.getType(Object.class);
+ static final Type TYPE_STRING = Type.getType(String.class);
+ static final Type TYPE_CLASS = Type.getType(Class.class);
+ static final Type TYPE_COLLECTION = Type.getType(Collection.class);
+ static final Type TYPE_COLLECTIONS = Type.getType(Collections.class);
+ static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class);
+ static final Type TYPE_LIST = Type.getType(List.class);
static final String CLINIT = "<clinit>";
static final String INIT = "<init>";
static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE);
static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
+ static final String SPECIALIZATION_TYPE = TYPE_SPECIALIZATION.getInternalName();
+ static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.getType(boolean.class));
+ static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.getType(boolean.class));
static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
static final String STRING_TYPE = TYPE_STRING.getInternalName();
@@ -123,11 +129,11 @@ public interface StringConstants {
static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC =
Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE);
static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC =
- Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY);
+ Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 =
- Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY);
+ Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 =
- Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_METHODHANDLE_ARRAY);
+ Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY);
// ScriptObject
static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
diff --git a/docs/DEVELOPER_README b/docs/DEVELOPER_README
index 9a2fffdf..5550b903 100644
--- a/docs/DEVELOPER_README
+++ b/docs/DEVELOPER_README
@@ -25,6 +25,14 @@ Example:
> java -Dnashorn.args="--lazy-complation --log=compiler" large-java-app-with-nashorn.jar
> ant -Dnashorn.args="--log=codegen" antjob
+SYSTEM PROPERTY: -Dnashorn.args.prepend=<string>
+
+This property behaves like nashorn.args, but adds the given arguments
+before the existing ones instead of after them. Later arguments will
+overwrite earlier ones, so this is useful for setting default arguments
+that can be overwritten.
+
+
SYSTEM PROPERTY: -Dnashorn.unstable.relink.threshold=x
This property controls how many call site misses are allowed before a
@@ -42,533 +50,38 @@ be split into several classes in order not to run out of bytecode space.
The default value is 0x8000 (32768).
-SYSTEM PROPERTY: -Dnashorn.compiler.intarithmetic
-
-(and integer arithmetic in general)
-
-<currently disabled - this is being refactored for update releases>
-
-Arithmetic operations in Nashorn (except bitwise ones) typically
-coerce the operands to doubles (as per the JavaScript spec). To switch
-this off and remain in integer mode, for example for "var x = a&b; var
-y = c&d; var z = x*y;", use this flag. This will force the
-multiplication of variables that are ints to be done with the IMUL
-bytecode and the result "z" to become an int.
-
-WARNING: Note that is is experimental only to ensure that type support
-exists for all primitive types. The generated code is unsound. This
-will be the case until we do optimizations based on it. There is a CR
-in Nashorn to do better range analysis, and ensure that this is only
-done where the operation can't overflow into a wider type. Currently
-no overflow checking is done, so at the moment, until range analysis
-has been completed, this option is turned off.
-
-We've experimented by using int arithmetic for everything and putting
-overflow checks afterwards, which would recompute the operation with
-the correct precision, but have yet to find a configuration where this
-is faster than just using doubles directly, even if the int operation
-does not overflow. Getting access to a JVM intrinsic that does branch
-on overflow would probably alleviate this.
-
-The future:
-
-We are transitioning to an optimistic type system that uses int
-arithmetic everywhere until proven wrong. The problem here is mostly
-catch an overflow exception and rolling back the state to a new method
-with less optimistic assumptions for an operation at a particular
-program point. This will most likely not be in the Java 8.0 release
-but likely end up in an update release
-
-For Java 8, several java.lang.Math methods like addExact, subExact and
-mulExact are available to help us. Experiments intrinsifying these
-show a lot of promise, and we have devised a system that basically
-does on stack replacement with exceptions in bytecode to revert
-erroneous assumptions. An explanation of how this works and what we
-are doing can be found here:
-http://www.slideshare.net/lagergren/lagergren-jvmls2013final
-
-Experiments with this show significant ~x2-3 performance increases on
-pretty much everything, provided that optimistic assumptions don't
-fail much. It will affect warmup time negatively, depending on how
-many erroneous too optimistic assumptions are placed in the code at
-compile time. We don't think this will be much of an issue.
-
-For example for a small benchmark that repeatedly executes this
-method taken from the Crypto Octane benchmark
-
-function am3(i,x,w,j,c,n) {
- var this_array = this.array;
- var w_array = w.array;
- var xl = x&0x3fff, xh = x>>14;
- while(--n >= 0) {
- var l = this_array[i]&0x3fff;
- var h = this_array[i++]>>14;
- var m = xh*l+h*xl;
- l = xl*l+((m&0x3fff)<<14)+w_array[j]+c;
- c = (l>>28)+(m>>14)+xh*h;
- w_array[j++] = l&0xfffffff;
- }
-
- return c;
-}
-
-The performance increase more than doubles. We are also working hard
-with the code generation team in the Java Virtual Machine to fix
-things that are lacking in invokedynamic performance, which is another
-area where a lot of ongoing performance work takes place
-
-"Pessimistic" bytecode for am3, guaranteed to be semantically correct:
-
-// access flags 0x9
- public static am3(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
- L0
- LINENUMBER 12 L0
- ALOAD 0
- INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- ASTORE 8
- L1
- LINENUMBER 13 L1
- ALOAD 3
- INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- ASTORE 9
- L2
- LINENUMBER 14 L2
- ALOAD 2
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
- SIPUSH 16383
- IAND
- ISTORE 10
- ALOAD 2
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
- BIPUSH 14
- ISHR
- ISTORE 11
- L3
- LINENUMBER 15 L3
- GOTO L4
- L5
- LINENUMBER 16 L5
- FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Double T java/lang/Object java/lang/Object I I] []
- ALOAD 8
- ALOAD 1
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)I [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- SIPUSH 16383
- IAND
- INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
- ASTORE 12
- L6
- LINENUMBER 17 L6
- ALOAD 8
- ALOAD 1
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
- DUP2
- DCONST_1
- DADD
- INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
- ASTORE 1
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;D)I [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- BIPUSH 14
- ISHR
- ISTORE 13
- L7
- LINENUMBER 18 L7
- ILOAD 11
- I2D
- ALOAD 12
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
- DMUL
- ILOAD 13
- I2D
- ILOAD 10
- I2D
- DMUL
- DADD
- DSTORE 14
- L8
- LINENUMBER 19 L8
- ILOAD 10
- I2D
- ALOAD 12
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
- DMUL
- DLOAD 14
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
- SIPUSH 16383
- IAND
- BIPUSH 14
- ISHL
- I2D
- DADD
- ALOAD 9
- ALOAD 4
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- INVOKEDYNAMIC ADD:ODO_D(DLjava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
- // arguments: none
- ]
- ALOAD 5
- INVOKEDYNAMIC ADD:OOO_I(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.runtimeBootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;)
- // arguments: none
- ]
- ASTORE 12
- L9
- LINENUMBER 20 L9
- ALOAD 12
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
- BIPUSH 28
- ISHR
- I2D
- DLOAD 14
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (D)I
- BIPUSH 14
- ISHR
- I2D
- DADD
- ILOAD 11
- I2D
- ILOAD 13
- I2D
- DMUL
- DADD
- INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
- ASTORE 5
- L10
- LINENUMBER 21 L10
- ALOAD 9
- ALOAD 4
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
- DUP2
- DCONST_1
- DADD
- INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
- ASTORE 4
- ALOAD 12
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toInt32 (Ljava/lang/Object;)I
- LDC 268435455
- IAND
- INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;DI)V [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- L4
- FRAME FULL [java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object java/lang/Object T java/lang/Object java/lang/Object I I] []
- ALOAD 6
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber (Ljava/lang/Object;)D
- LDC -1.0
- DADD
- DUP2
- INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;
- ASTORE 6
- DCONST_0
- DCMPL
- IFGE L5
- L11
- LINENUMBER 24 L11
- ALOAD 5
- ARETURN
-
-"Optimistic" bytecode that requires invalidation on e.g overflow. Factor
-x2-3 speedup:
-
-public static am3(Ljava/lang/Object;IILjava/lang/Object;III)I
- L0
- LINENUMBER 12 L0
- ALOAD 0
- INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- ASTORE 8
- L1
- LINENUMBER 13 L1
- ALOAD 3
- INVOKEDYNAMIC dyn:getProp|getElem|getMethod:array(Ljava/lang/Object;)Ljava/lang/Object; [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- ASTORE 9
- L2
- LINENUMBER 14 L2
- ILOAD 2
- SIPUSH 16383
- IAND
- ISTORE 10
- ILOAD 2
- BIPUSH 14
- ISHR
- ISTORE 11
- L3
- LINENUMBER 15 L3
- GOTO L4
- L5
- LINENUMBER 16 L5
- FRAME FULL [java/lang/Object I I java/lang/Object I I I T java/lang/Object java/lang/Object I I] []
- ALOAD 8
- ILOAD 1
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- SIPUSH 16383
- IAND
- ISTORE 12
- L6
- LINENUMBER 17 L6
- ALOAD 8
- ILOAD 1
- DUP
- ICONST_1
- IADD
- ISTORE 1
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- BIPUSH 14
- ISHR
- ISTORE 13
- L7
- LINENUMBER 18 L7
- ILOAD 11
- ILOAD 12
- BIPUSH 8
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
- ILOAD 13
- ILOAD 10
- BIPUSH 9
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
- IADD
- ISTORE 14
- L8
- LINENUMBER 19 L8
- ILOAD 10
- ILOAD 12
- BIPUSH 11
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
- ILOAD 14
- SIPUSH 16383
- IAND
- BIPUSH 14
- ISHL
- IADD
- ALOAD 9
- ILOAD 4
- INVOKEDYNAMIC dyn:getElem|getProp|getMethod(Ljava/lang/Object;I)I [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- IADD
- ILOAD 5
- IADD
- ISTORE 12
- L9
- LINENUMBER 20 L9
- ILOAD 12
- BIPUSH 28
- ISHR
- ILOAD 14
- BIPUSH 14
- ISHR
- IADD
- ILOAD 11
- ILOAD 13
- BIPUSH 21
- INVOKESTATIC jdk/nashorn/internal/runtime/JSType.mulExact (III)I
- IADD
- ISTORE 5
- L10
- LINENUMBER 21 L10
- ALOAD 9
- ILOAD 4
- DUP
- ICONST_1
- IADD
- ISTORE 4
- ILOAD 12
- LDC 268435455
- IAND
- INVOKEDYNAMIC dyn:setElem|setProp(Ljava/lang/Object;II)V [
- // handle kind 0x6 : INVOKESTATIC
- jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap((Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;)
- // arguments:
- 0
- ]
- L4
- FRAME SAME
- ILOAD 6
- ICONST_M1
- IADD
- DUP
- ISTORE 6
- ICONST_0
- IF_ICMPGE L5
- L11
- LINENUMBER 24 L11
- ILOAD 5
- IRETURN
-
-
-SYSTEM PROPERTY: -Dnashorn.codegen.debug, -Dnashorn.codegen.debug.trace=<x>
+SYSTEM PROPERTY: -Dnashorn.serialize.compression=<x>
-See the description of the codegen logger below.
+This property sets the compression level used when deflating serialized
+AST structures of anonymous split functions. Valid values range from 0 to 9,
+the default value is 4. Higher values will reduce memory size of serialized
+AST but increase CPU usage required for compression.
-SYSTEM_PROPERTY: -Dnashorn.fields.debug
+SYSTEM PROPERTY: -Dnashorn.codegen.debug.trace=<x>
-See the description on the fields logger below.
+See the description of the codegen logger below.
-SYSTEM PROPERTY: -Dnashorn.fields.dual
+SYSTEM PROPERTY: -Dnashorn.fields.objects
-When this property is true, Nashorn will attempt to use primitive
-fields for AccessorProperties (currently just AccessorProperties, not
-spill properties). Memory footprint for script objects will increase,
-as we need to maintain both a primitive field (a long) as well as an
-Object field for the property value. Ints are represented as the 32
-low bits of the long fields. Doubles are represented as the
-doubleToLongBits of their value. This way a single field can be used
-for all primitive types. Packing and unpacking doubles to their bit
-representation is intrinsified by the JVM and extremely fast.
+When this property is true, Nashorn will only use object fields for
+AccessorProperties. This means that primitive values must be boxed
+when stored in a field, which is significantly slower than using
+primitive fields.
-While dual fields in theory runs significantly faster than Object
-fields due to reduction of boxing and memory allocation overhead,
-there is still work to be done to make this a general purpose
-solution. Research is ongoing.
+By default, Nashorn uses dual object and long fields. Ints are
+represented as the 32 low bits of the long fields. Doubles are
+represented as the doubleToLongBits of their value. This way a
+single field can be used for all primitive types. Packing and
+unpacking doubles to their bit representation is intrinsified by
+the JVM and extremely fast.
In the future, this might complement or be replaced by experimental
feature sun.misc.TaggedArray, which has been discussed on the mlvm
mailing list. TaggedArrays are basically a way to share data space
between primitives and references, and have the GC understand this.
-As long as only primitive values are written to the fields and enough
-type information exists to make sure that any reads don't have to be
-uselessly boxed and unboxed, this is significantly faster than the
-standard "Objects only" approach that currently is the default. See
-test/examples/dual-fields-micro.js for an example that runs twice as
-fast with dual fields as without them. Here, the compiler, can
-determine that we are dealing with numbers only throughout the entire
-property life span of the properties involved.
-
-If a "real" object (not a boxed primitive) is written to a field that
-has a primitive representation, its callsite is relinked and an Object
-field is used forevermore for that particular field in that
-PropertyMap and its children, even if primitives are later assigned to
-it.
-
-As the amount of compile time type information is very small in a
-dynamic language like JavaScript, it is frequently the case that
-something has to be treated as an object, because we don't know any
-better. In reality though, it is often a boxed primitive is stored to
-an AccessorProperty. The fastest way to handle this soundly is to use
-a callsite typecheck and avoid blowing the field up to an Object. We
-never revert object fields to primitives. Ping-pong:ing back and forth
-between primitive representation and Object representation would cause
-fatal performance overhead, so this is not an option.
-
-For a general application the dual fields approach is still slower
-than objects only fields in some places, about the same in most cases,
-and significantly faster in very few. This is due the program using
-primitives, but we still can't prove it. For example "local_var a =
-call(); field = a;" may very well write a double to the field, but the
-compiler dare not guess a double type if field is a local variable,
-due to bytecode variables being strongly typed and later non
-interchangeable. To get around this, the entire method would have to
-be replaced and a continuation retained to restart from. We believe
-that the next steps we should go through are instead:
-
-1) Implement method specialization based on callsite, as it's quite
-frequently the case that numbers are passed around, but currently our
-function nodes just have object types visible to the compiler. For
-example "var b = 17; func(a,b,17)" is an example where two parameters
-can be specialized, but the main version of func might also be called
-from another callsite with func(x,y,"string").
-
-2) This requires lazy jitting as the functions have to be specialized
-per callsite.
-
-Even though "function square(x) { return x*x }" might look like a
-trivial function that can always only take doubles, this is not
-true. Someone might have overridden the valueOf for x so that the
-toNumber coercion has side effects. To fulfil JavaScript semantics,
-the coercion has to run twice for both terms of the multiplication
-even if they are the same object. This means that call site
-specialization is necessary, not parameter specialization on the form
-"function square(x) { var xd = (double)x; return xd*xd; }", as one
-might first think.
-
-Generating a method specialization for any variant of a function that
-we can determine by types at compile time is a combinatorial explosion
-of byte code (try it e.g. on all the variants of am3 in the Octane
-benchmark crypto.js). Thus, this needs to be lazy
-
-3) Optimistic callsite writes, something on the form
-
-x = y; //x is a field known to be a primitive. y is only an object as
-far as we can tell
-
-turns into
-
-try {
- x = (int)y;
-} catch (X is not an integer field right now | ClassCastException e) {
- x = y;
-}
-
-Mini POC shows that this is the key to a lot of dual field performance
-in seemingly trivial micros where one unknown object, in reality
-actually a primitive, foils it for us. Very common pattern. Once we
-are "all primitives", dual fields runs a lot faster than Object fields
-only.
-
-We still have to deal with objects vs primitives for local bytecode
-slots, possibly through code copying and versioning.
-
-The Future:
-
-We expect the usefulness of dual fields to increase significantly
-after the optimistic type system described in the section on
-integer arithmetic above is implemented.
-
SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=[<x>[,*]],
-Dnashorn.compiler.symbol.stacktrace=[<x>[,*]]
@@ -628,6 +141,9 @@ for invoking a particular script function.
"identical" - this method compares two script objects for reference
equality. It is a == Java comparison
+"equals" - Returns true if two objects are either referentially
+identical or equal as defined by java.lang.Object.equals.
+
"dumpCounters" - will dump the debug counters' current values to
stdout.
@@ -648,66 +164,66 @@ Finally we count callsite misses on a per callsite bases, which occur
when a callsite has to be relinked, due to a previous assumption of
object layout being invalidated.
+"getContext" - return the current Nashorn context.
-SYSTEM PROPERTY: -Dnashorn.methodhandles.debug,
--Dnashorn.methodhandles.debug=create
+"equalWithoutType" - Returns true if if the two objects are both
+property maps, and they have identical properties in the same order,
+but allows the properties to differ in their types.
-If this property is enabled, each MethodHandle related call that uses
-the java.lang.invoke package gets its MethodHandle intercepted and an
-instrumentation printout of arguments and return value appended to
-it. This shows exactly which method handles are executed and from
-where. (Also MethodTypes and SwitchPoints). This can be augmented with
-more information, for example, instance count, by subclassing or
-further extending the TraceMethodHandleFactory implementation in
-MethodHandleFactory.java.
+"diffPropertyMaps" Returns a diagnostic string representing the difference
+of two property maps.
+
+"getClass" - Returns the Java class of an object, or undefined if null.
+
+"toJavaString" - Returns the Java toString representation of an object.
+
+"toIdentString" - Returns a string representation of an object consisting
+of its java class name and hash code.
+
+"getListenerCount" - Return the number of property listeners for a
+script object.
+
+"getEventQueueCapacity" - Get the capacity of the event queue.
+
+"setEventQueueCapacity" - Set the event queue capacity.
+
+"addRuntimeEvent" - Add a runtime event to the runtime event queue.
+The queue has a fixed size (see -Dnashorn.runtime.event.queue.size)
+and the oldest entry will be thrown out of the queue is about to overflow.
+
+"expandEventQueueCapacity" - Expands the event queue capacity,
+or truncates if capacity is lower than current capacity. Then only
+the newest entries are kept.
+
+"clearRuntimeEvents" - Clear the runtime event queue.
-If the property is specialized with "=create" as its option,
-instrumentation will be shown for method handles upon creation time
-rather than at runtime usage.
+"removeRuntimeEvent" - Remove a specific runtime event from the event queue.
+
+"getRuntimeEvents" - Return all runtime events in the queue as an array.
+
+"getLastRuntimeEvent" - Return the last runtime event in the queue.
SYSTEM PROPERTY: -Dnashorn.methodhandles.debug.stacktrace
-This does the same as nashorn.methodhandles.debug, but when enabled
-also dumps the stack trace for every instrumented method handle
-operation. Warning: This is enormously verbose, but provides a pretty
+This enhances methodhandles logging (see below) to also dump the
+stack trace for every instrumented method handle operation.
+Warning: This is enormously verbose, but provides a pretty
decent "grep:able" picture of where the calls are coming from.
-See the description of the codegen logger below for a more verbose
-description of this option
-
-
-SYSTEM PROPERTY: -Dnashorn.scriptfunction.specialization.disable
-
-There are several "fast path" implementations of constructors and
-functions in the NativeObject classes that, in their original form,
-take a variable amount of arguments. Said functions are also declared
-to take Object parameters in their original form, as this is what the
-JavaScript specification mandates.
-However, we often know quite a lot more at a callsite of one of these
-functions. For example, Math.min is called with a fixed number (2) of
-integer arguments. The overhead of boxing these ints to Objects and
-folding them into an Object array for the generic varargs Math.min
-function is an order of magnitude slower than calling a specialized
-implementation of Math.min that takes two integers. Specialized
-functions and constructors are identified by the tag
-@SpecializedFunction and @SpecializedConstructor in the Nashorn
-code. The linker will link in the most appropriate (narrowest types,
-right number of types and least number of arguments) specialization if
-specializations are available.
-
-Every ScriptFunction may carry specializations that the linker can
-choose from. This framework will likely be extended for user defined
-functions. The compiler can often infer enough parameter type info
-from callsites for in order to generate simpler versions with less
-generic Object types. This feature depends on future lazy jitting, as
-there tend to be many calls to user defined functions, some where the
-callsite can be specialized, some where we mostly see object
-parameters even at the callsite.
-
-If this system property is set to true, the linker will not attempt to
-use any specialized function or constructor for native objects, but
-just call the generic one.
+
+SYSTEM PROPERTY: -Dnashorn.cce
+
+Setting this system property causes the Nashorn linker to rely on
+ClassCastExceptions for triggering a callsite relink. If not set, the linker
+will add an explicit instanceof guard.
+
+
+SYSTEM PROPERTY: -Dnashorn.spill.threshold=<x>
+
+This property sets the number of fields in an object from which to use
+generic array based spill storage instead of Java fields. The default value
+is 256.
SYSTEM PROPERTY: -Dnashorn.tcs.miss.samplePercent=<x>
@@ -719,8 +235,47 @@ system property can be used to constrain the percentage of misses that
should be logged. Typically this is set to 1 or 5 (percent). 1% is the
default value.
+SYSTEM PROPERTY: -Dnashorn.persistent.code.cache
+
+This property can be used to set the directory where Nashorn stores
+serialized script classes generated with the -pcc/--persistent-code-cache
+option. The default directory name is "nashorn_code_cache".
+
+
+SYSTEM PROPERTY: -Dnashorn.typeInfo.maxFiles
+
+Maximum number of files to store in the type info cache. The type info cache
+is used to cache type data of JavaScript functions when running with
+optimistic types (-ot/--optimistic-types). There is one file per JavaScript
+function in the cache.
+
+The default value is 0 which means the feature is disabled. Setting this
+to something like 20000 is probably good enough for most applications and
+will usually cap the cache directory to about 80MB presuming a 4kB
+filesystem allocation unit. Set this to "unlimited" to run without limit.
+
+If the value is not 0 or "unlimited", Nashorn will spawn a cleanup thread
+that makes sure the number of files in the cache does not exceed the given
+value by deleting the least recently modified files.
+
+
+SYSTEM PROPERTY: -Dnashorn.typeInfo.cacheDir
+
+This property can be used to set the directory where Nashorn stores the
+type info cache when -Dnashorn.typeInfo.maxFiles is set to a nonzero
+value. The default location is platform specific. On Windows, it is
+"${java.io.tmpdir}\com.oracle.java.NashornTypeInfo". On Linux and
+Solaris it is "~/.cache/com.oracle.java.NashornTypeInfo". On Mac OS X,
+it is "~/Library/Caches/com.oracle.java.NashornTypeInfo".
+
+
+SYSTEM PROPERTY: -Dnashorn.typeInfo.cleanupDelaySeconds=<value>
-SYSTEM_PROPERTY: -Dnashorn.profilefile=<filename>
+This sets the delay between cleanups of the typeInfo cache, in seconds.
+The default delay is 20 seconds.
+
+
+SYSTEM PROPERTY: -Dnashorn.profilefile=<filename>
When running with the profile callsite options (-pcs), Nashorn will
dump profiling data for all callsites to stderr as a shutdown hook. To
@@ -736,26 +291,11 @@ JDK's java.util.regex package. Set this property to "joni" to install
an implementation based on Joni, the regular expression engine used by
the JRuby project. The default value for this flag is "joni"
+SYSTEM PROPERTY: -Dnashorn.runtime.event.queue.size=<value>
-SYSTEM PROPERTY: -Dnashorn.time
-
-This enables timers for various phases of script compilation. The timers
-will be dumped when the Nashorn process exits. We see a percentage value
-of how much time was spent not executing bytecode (i.e. compilation and
-internal tasks) at the end of the report.
-
-Here is an example:
-
-[JavaScript Parsing] 61 ms
-[Constant Folding] 11 ms
-[Control Flow Lowering] 26 ms
-[Type Attribution] 81 ms
-[Range Analysis] 0 ms
-[Code Splitting] 29 ms
-[Type Finalization] 19 ms
-[Bytecode Generation] 189 ms
-[Code Installation] 7 ms
-Total runtime: 508 ms (Non-runtime: 423 ms [83%])
+Nashorn provides a fixed sized runtime event queue for debugging purposes.
+See -Dnashorn.debug for methods to access the event queue.
+The default value is 1024.
===============
2. The loggers.
@@ -787,7 +327,9 @@ times on the same command line, with the same effect.
For example: --log=codegen,fields:finest is equivalent to
--log=codegen:info --log=fields:finest
-The subsystems that currently support logging are:
+The following is an incomplete list of subsystems that currently
+support logging. Look for classes implementing
+jdk.nashorn.internal.runtime.logging.Loggable for more loggers.
* compiler
@@ -800,6 +342,14 @@ settings that all the tiers of codegen (e.g. Lower and CodeGenerator)
use.s
+* recompile
+
+This logger shows information about recompilation of scripts and
+functions at runtime. Recompilation may happen because a function
+was called with different parameter types, or because an optimistic
+assumption failed while executing a function with -ot/--optimistic-types.
+
+
* codegen
The code generator is the emitter stage of the code pipeline, and
@@ -856,25 +406,13 @@ and inlining finally blocks.
Lower is also responsible for determining control flow information
like end points.
+* symbols
-* attr
-
-The lowering annotates a FunctionNode with symbols for each identifier
-and transforms high level constructs into lower level ones, that the
-CodeGenerator consumes.
-
-Lower logging typically outputs things like post pass actions,
-insertions of casts because symbol types have been changed and type
-specialization information. Currently very little info is generated by
-this logger. This will probably change.
+The symbols logger tracks the assignment os symbols to identifiers.
+* scopedepths
-* finalize
-
-This --log=finalize log option outputs information for type finalization,
-the third tier of the compiler. This means things like placement of
-specialized scope nodes or explicit conversions.
-
+This logs the calculation of scope depths for non-local symbols.
* fields
@@ -887,6 +425,49 @@ etc. It will also show the internal representation of respective field
(Object in the normal case, unless running with the dual field
representation)
+* time
+
+This enables timers for various phases of script compilation. The timers
+will be dumped when the Nashorn process exits. We see a percentage value
+of how much time was spent not executing bytecode (i.e. compilation and
+internal tasks) at the end of the report.
+
+A finer level than "info" will show individual compilation timings as they
+happen.
+
+Here is an example:
+
+[time] Accumulated complation phase Timings:
+[time]
+[time] 'JavaScript Parsing' 1076 ms
+[time] 'Constant Folding' 159 ms
+[time] 'Control Flow Lowering' 303 ms
+[time] 'Program Point Calculation' 282 ms
+[time] 'Builtin Replacement' 71 ms
+[time] 'Code Splitting' 670 ms
+[time] 'Symbol Assignment' 474 ms
+[time] 'Scope Depth Computation' 249 ms
+[time] 'Optimistic Type Assignment' 186 ms
+[time] 'Local Variable Type Calculation' 526 ms
+[time] 'Bytecode Generation' 5177 ms
+[time] 'Class Installation' 1854 ms
+[time]
+[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
+
+* methodhandles
+
+If this logger is enabled, each MethodHandle related call that uses
+the java.lang.invoke package gets its MethodHandle intercepted and an
+instrumentation printout of arguments and return value appended to
+it. This shows exactly which method handles are executed and from
+where. (Also MethodTypes and SwitchPoints).
+
+* classcache
+
+This logger shows information about reusing code classes using the
+in-memory class cache. Nashorn will try to avoid compilation of
+scripts by using existing classes. This can significantly improve
+performance when repeatedly evaluating the same script.
=======================
3. Undocumented options
@@ -914,11 +495,10 @@ A short summary follows:
-cp, -classpath (-cp path. Specify where to find user class files.)
- -co, --compile-only (Compile script without running. Exit after compilation)
+ -co, --compile-only (Compile without running.)
param: [true|false] default: false
- -d, --dump-debug-dir (specify a destination directory to dump class files.
- This must be combined with the --compile-only option to work)
+ -d, --dump-debug-dir (specify a destination directory to dump class files.)
param: <path>
--debug-lines (Generate line number table in .class files.)
@@ -954,10 +534,6 @@ A short summary follows:
-h, -help (Print help for command line flags.)
param: [true|false] default: false
- --lazy-compilation (EXPERIMENTAL: Use lazy code generation strategies - do not compile
- the entire script at once.)
- param: [true|false] default: false
-
--loader-per-compile (Create a new class loader per compile.)
param: [true|false] default: true
@@ -965,16 +541,16 @@ A short summary follows:
param: <locale> default: en-US
--log (Enable logging of a given level for a given number of sub systems.
- [for example: --log=fields:finest,codegen:info])
+ [for example: --log=fields:finest,codegen:info].)
param: <module:level>,*
- -nj, --no-java (No Java support)
+ -nj, --no-java (Disable Java support.)
param: [true|false] default: false
- -nse, --no-syntax-extensions (No non-standard syntax extensions)
+ -nse, --no-syntax-extensions (Disallow non-standard syntax extensions.)
param: [true|false] default: false
- -nta, --no-typed-arrays (No Typed arrays support)
+ -nta, --no-typed-arrays (Disable typed arrays support.)
param: [true|false] default: false
--parse-only (Parse without compiling.)
@@ -983,13 +559,15 @@ A short summary follows:
--print-ast (Print abstract syntax tree.)
param: [true|false] default: false
- --print-code (Print bytecode.)
- param: [true|false] default: false
+ -pc, --print-code (Print generated bytecode. If a directory is specified, nothing will
+ be dumped to stderr. Also, in that case, .dot files will be generated
+ for all functions or for the function with the specified name only.)
+ param: [dir:<output-dir>,function:<name>]
--print-lower-ast (Print lowered abstract syntax tree.)
param: [true|false] default: false
- --print-lower-parse (Print the parse tree after lowering.)
+ -plp, --print-lower-parse (Print the parse tree after lowering.)
param: [true|false] default: false
--print-mem-usage (Print memory usage of IR after each compile stage.)
@@ -998,7 +576,7 @@ A short summary follows:
--print-no-newline (Print function will not print new line char.)
param: [true|false] default: false
- --print-parse (Print the parse tree.)
+ -pp, --print-parse (Print the parse tree.)
param: [true|false] default: false
--print-symbols (Print the symbol table.)
@@ -1007,21 +585,13 @@ A short summary follows:
-pcs, --profile-callsites (Dump callsite profile data.)
param: [true|false] default: false
- --range-analysis (EXPERIMENTAL: Do range analysis using known compile time types,
- and try to narrow number types)
- param: [true|false] default: false
-
-scripting (Enable scripting features.)
param: [true|false] default: false
- --specialize-calls (EXPERIMENTAL: Specialize all or a set of method according
- to callsite parameter types)
- param: [=function_1,...,function_n]
-
- --stderr (Redirect stderr to a filename or to another tty, e.g. stdout)
+ --stderr (Redirect stderr to a filename or to another tty, e.g. stdout.)
param: <output console>
- --stdout (Redirect stdout to a filename or to another tty, e.g. stderr)
+ --stdout (Redirect stdout to a filename or to another tty, e.g. stderr.)
param: <output console>
-strict (Run scripts in strict mode.)
@@ -1031,7 +601,7 @@ A short summary follows:
param: <timezone> default: Europe/Stockholm
-tcs, --trace-callsites (Enable callsite trace mode. Options are: miss [trace callsite misses]
- enterexit [trace callsite enter/exit], objects [print object properties])
+ enterexit [trace callsite enter/exit], objects [print object properties].)
param: [=[option,]*]
--verify-code (Verify byte code before running.)
diff --git a/docs/genshelldoc.js b/docs/genshelldoc.js
index 3d11a471..96473512 100644
--- a/docs/genshelldoc.js
+++ b/docs/genshelldoc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -61,7 +61,7 @@ PREFIX);
for each (opt in Options.validOptions) {
-var isTimezone = (opt.type == "timezone");
+var isTimezone = (opt.type == "timezone");
var defValue = opt.defaultValue;
if (defValue == null) {
defValue = "&lt;none&gt;";
diff --git a/docs/source/EvalFile.java b/docs/source/EvalFile.java
index 6bb4e381..b12e91bb 100644
--- a/docs/source/EvalFile.java
+++ b/docs/source/EvalFile.java
@@ -29,14 +29,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class EvalFile {
- public static void main(String[] args) throws Exception {
+ public static void main(final String[] args) throws Exception {
// create a script engine manager
- ScriptEngineManager factory = new ScriptEngineManager();
+ final ScriptEngineManager factory = new ScriptEngineManager();
// create JavaScript engine
- ScriptEngine engine = factory.getEngineByName("nashorn");
+ final ScriptEngine engine = factory.getEngineByName("nashorn");
// evaluate JavaScript code from given file - specified by first argument
engine.eval(new java.io.FileReader(args[0]));
}
diff --git a/docs/source/EvalScript.java b/docs/source/EvalScript.java
index 7fcbe1cd..49f581de 100644
--- a/docs/source/EvalScript.java
+++ b/docs/source/EvalScript.java
@@ -29,14 +29,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class EvalScript {
- public static void main(String[] args) throws Exception {
+ public static void main(final String[] args) throws Exception {
// create a script engine manager
- ScriptEngineManager factory = new ScriptEngineManager();
+ final ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
- ScriptEngine engine = factory.getEngineByName("nashorn");
+ final ScriptEngine engine = factory.getEngineByName("nashorn");
// evaluate JavaScript code from String
engine.eval("print('Hello, World')");
}
diff --git a/docs/source/InvokeScriptFunction.java b/docs/source/InvokeScriptFunction.java
index 26de36c4..5ce1cae0 100644
--- a/docs/source/InvokeScriptFunction.java
+++ b/docs/source/InvokeScriptFunction.java
@@ -29,22 +29,25 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class InvokeScriptFunction {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
- String script = "function hello(name) { print('Hello, ' + name); }";
+ final String script = "function hello(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
- Invocable inv = (Invocable) engine;
+ final Invocable inv = (Invocable) engine;
// invoke the global function named "hello"
inv.invokeFunction("hello", "Scripting!!" );
diff --git a/docs/source/InvokeScriptMethod.java b/docs/source/InvokeScriptMethod.java
index a3f5ece7..d3cc788d 100644
--- a/docs/source/InvokeScriptMethod.java
+++ b/docs/source/InvokeScriptMethod.java
@@ -29,26 +29,29 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class InvokeScriptMethod {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String. This code defines a script object 'obj'
// with one method called 'hello'.
- String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
+ final String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
- Invocable inv = (Invocable) engine;
+ final Invocable inv = (Invocable) engine;
// get script object on which we want to call the method
- Object obj = engine.get("obj");
+ final Object obj = engine.get("obj");
// invoke the method named "hello" on the script object "obj"
inv.invokeMethod(obj, "hello", "Script Method !!" );
diff --git a/docs/source/MultiScopes.java b/docs/source/MultiScopes.java
index 6c4fa2a2..ff4f65b4 100644
--- a/docs/source/MultiScopes.java
+++ b/docs/source/MultiScopes.java
@@ -29,12 +29,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleScriptContext;
+@SuppressWarnings("javadoc")
public class MultiScopes {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
engine.put("x", "hello");
// print global variable "x"
@@ -42,9 +47,9 @@ public class MultiScopes {
// the above line prints "hello"
// Now, pass a different script context
- ScriptContext newContext = new SimpleScriptContext();
+ final ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
- Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
+ final Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
// add new variable "x" to the new engineScope
engineScope.put("x", "world");
diff --git a/docs/source/RunnableImpl.java b/docs/source/RunnableImpl.java
index 1d858d40..2b5113b1 100644
--- a/docs/source/RunnableImpl.java
+++ b/docs/source/RunnableImpl.java
@@ -29,28 +29,31 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class RunnableImpl {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
- String script = "function run() { print('run called'); }";
+ final String script = "function run() { print('run called'); }";
// evaluate script
engine.eval(script);
- Invocable inv = (Invocable) engine;
+ final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script functions with the matching name.
- Runnable r = inv.getInterface(Runnable.class);
+ final Runnable r = inv.getInterface(Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
- Thread th = new Thread(r);
+ final Thread th = new Thread(r);
th.start();
th.join();
}
diff --git a/docs/source/RunnableImplObject.java b/docs/source/RunnableImplObject.java
index 877f8c15..0d5f5032 100644
--- a/docs/source/RunnableImplObject.java
+++ b/docs/source/RunnableImplObject.java
@@ -29,31 +29,34 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class RunnableImplObject {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
- String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
+ final String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
// evaluate script
engine.eval(script);
// get script object on which we want to implement the interface with
- Object obj = engine.get("obj");
+ final Object obj = engine.get("obj");
- Invocable inv = (Invocable) engine;
+ final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script methods of object 'obj'
- Runnable r = inv.getInterface(obj, Runnable.class);
+ final Runnable r = inv.getInterface(obj, Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
- Thread th = new Thread(r);
+ final Thread th = new Thread(r);
th.start();
th.join();
}
diff --git a/docs/source/ScriptVars.java b/docs/source/ScriptVars.java
index 7e16cfca..c697431d 100644
--- a/docs/source/ScriptVars.java
+++ b/docs/source/ScriptVars.java
@@ -29,15 +29,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import javax.script.*;
-import java.io.*;
+import java.io.File;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+@SuppressWarnings("javadoc")
public class ScriptVars {
- public static void main(String[] args) throws Exception {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("nashorn");
+ public static void main(final String[] args) throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine engine = manager.getEngineByName("nashorn");
- File f = new File("test.txt");
+ final File f = new File("test.txt");
// expose File object as variable to script
engine.put("file", f);
diff --git a/docs/source/importpackageclass.js b/docs/source/importpackageclass.js
index afc02a9b..224debd6 100644
--- a/docs/source/importpackageclass.js
+++ b/docs/source/importpackageclass.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -32,7 +32,7 @@
// load compatibility script
load("nashorn:mozilla_compat.js");
-// Import Java packages and classes
+// Import Java packages and classes
// like import package.*; in Java
importPackage(java.awt);
// like import java.awt.Frame in Java
diff --git a/docs/source/javaarray.js b/docs/source/javaarray.js
index d0de9124..65961910 100644
--- a/docs/source/javaarray.js
+++ b/docs/source/javaarray.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/javaextend.js b/docs/source/javaextend.js
index 408da320..f1c6256b 100644
--- a/docs/source/javaextend.js
+++ b/docs/source/javaextend.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/javaimporter.js b/docs/source/javaimporter.js
index 3bd07988..5004ce88 100644
--- a/docs/source/javaimporter.js
+++ b/docs/source/javaimporter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/javatypes.js b/docs/source/javatypes.js
index e0b6f07b..82392ec4 100644
--- a/docs/source/javatypes.js
+++ b/docs/source/javatypes.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/overload.js b/docs/source/overload.js
index 2407d0c5..a2905f94 100644
--- a/docs/source/overload.js
+++ b/docs/source/overload.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,6 +31,6 @@
var out = java.lang.System.out;
-// select a particular print function
+// select a particular print function
out["println(java.lang.Object)"]("hello");
diff --git a/docs/source/runnable.js b/docs/source/runnable.js
index 67cd31c6..346c2522 100644
--- a/docs/source/runnable.js
+++ b/docs/source/runnable.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/samfunc.js b/docs/source/samfunc.js
index c870076e..dbb321d0 100644
--- a/docs/source/samfunc.js
+++ b/docs/source/samfunc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/docs/source/test.js b/docs/source/test.js
index 6323c386..56e96ef2 100644
--- a/docs/source/test.js
+++ b/docs/source/test.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/make/BuildNashorn.gmk b/make/BuildNashorn.gmk
index a987874c..683d4624 100644
--- a/make/BuildNashorn.gmk
+++ b/make/BuildNashorn.gmk
@@ -65,7 +65,7 @@ $(eval $(call SetupJavaCompilation,BUILD_NASGEN, \
SETUP := GENERATE_NEWBYTECODE_DEBUG, \
SRC := $(NASGEN_SRC) $(ASM_SRC), \
BIN := $(NASHORN_OUTPUTDIR)/nasgen_classes, \
- ADD_JAVAC_FLAGS := -cp $(NASHORN_OUTPUTDIR)/nashorn_classes))
+ ADD_JAVAC_FLAGS := -bootclasspath "$(BOOT_RTJAR)$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes"))
# Nasgen needs nashorn classes
$(BUILD_NASGEN): $(BUILD_NASHORN)
diff --git a/make/build-benchmark.xml b/make/build-benchmark.xml
index ac87fc12..ae76718f 100644
--- a/make/build-benchmark.xml
+++ b/make/build-benchmark.xml
@@ -1,381 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!--
- Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
+ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
-->
-<project name="nashorn-benchmarks" default="all" basedir="..">
- <target name="octane-init" depends="jar">
- <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes pdfjs raytrace regexp richards splay"/>
- </target>
-
- <!-- ignore benchmarks where rhino crashes -->
- <target name="octane-init-rhino" depends="jar">
- <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes raytrace regexp richards splay"/>
- </target>
+
+<project
+ name="nashorn-benchmarks"
+ default="all"
+ basedir=".."
+ xmlns:if="ant:if">
+
+ <!--
+ Below are the octane benchmarks that should be run.
+ The ones that are excluded, as Nashorn currently has
+ some issues with them (functionality or performance)
+ are commented out
+ -->
<!-- box2d -->
- <target name="octane-box2d" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="box2d"/>
- </antcall>
+ <target name="octane-box2d" depends="octane-box2d-nashorn"/>
+ <target name="octane-box2d-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.box2d" runtime="nashorn"/>
</target>
-
<target name="octane-box2d-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="box2d"/>
- </antcall>
+ <run-one cond="octane.benchmark.box2d" runtime="v8"/>
</target>
-
<target name="octane-box2d-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="box2d"/>
- </antcall>
+ <run-one cond="octane.benchmark.box2d" runtime="rhino"/>
</target>
-
- <!-- code-load -->
- <target name="octane-code-load" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="code-load"/>
- </antcall>
+ <!-- code-load -->
+ <target name="octane-code-load" depends="octane-code-load-nashorn"/>
+ <target name="octane-code-load-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.code-load" runtime="nashorn"/>
</target>
-
<target name="octane-code-load-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="code-load"/>
- </antcall>
+ <run-one cond="octane.benchmark.code-load" runtime="v8"/>
</target>
-
<target name="octane-code-load-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="code-load"/>
- </antcall>
+ <run-one cond="octane.benchmark.code-load" runtime="rhino"/>
</target>
-
<!-- crypto -->
- <target name="octane-crypto" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="crypto"/>
- </antcall>
+ <target name="octane-crypto" depends="octane-crypto-nashorn"/>
+ <target name="octane-crypto-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.crypto" runtime="nashorn"/>
</target>
-
<target name="octane-crypto-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="crypto"/>
- </antcall>
+ <run-one cond="octane.benchmark.crypto" runtime="v8"/>
</target>
-
<target name="octane-crypto-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="crypto"/>
- </antcall>
+ <run-one cond="octane.benchmark.crypto" runtime="rhino"/>
</target>
-
<!-- deltablue -->
- <target name="octane-deltablue" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="deltablue"/>
- </antcall>
+ <target name="octane-deltablue" depends="octane-deltablue-nashorn"/>
+ <target name="octane-deltablue-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.deltablue" runtime="nashorn"/>
</target>
-
<target name="octane-deltablue-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="deltablue"/>
- </antcall>
+ <run-one cond="octane.benchmark.deltablue" runtime="v8"/>
</target>
-
<target name="octane-deltablue-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="deltablue"/>
- </antcall>
+ <run-one cond="octane.benchmark.deltablue" runtime="rhino"/>
</target>
-
<!-- earley-boyer -->
- <target name="octane-earley-boyer" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="earley-boyer"/>
- </antcall>
+ <target name="octane-earley-boyer" depends="octane-earley-boyer-nashorn"/>
+ <target name="octane-earley-boyer-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.earley-boyer" runtime="nashorn"/>
</target>
-
<target name="octane-earley-boyer-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="earley-boyer"/>
- </antcall>
+ <run-one cond="octane.benchmark.earley-boyer" runtime="v8"/>
</target>
-
<target name="octane-earley-boyer-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="earley-boyer"/>
- </antcall>
+ <run-one cond="octane.benchmark.earley-boyer" runtime="rhino"/>
</target>
-
-
- <!-- gbemu -->
- <target name="octane-gbemu" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="gbemu"/>
- </antcall>
+
+ <!-- gbemu -->
+ <target name="octane-gbemu" depends="octane-gbemu-nashorn"/>
+ <target name="octane-gbemu-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.gbemu" runtime="nashorn"/>
</target>
-
<target name="octane-gbemu-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="gbemu"/>
- </antcall>
+ <run-one cond="octane.benchmark.gbemu" runtime="v8"/>
</target>
-
<target name="octane-gbemu-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="gbemu"/>
- </antcall>
+ <run-one cond="octane.benchmark.gbemu" runtime="rhino"/>
</target>
-
- <!-- mandreel -->
- <target name="octane-mandreel" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="mandreel"/>
- </antcall>
+ <!-- mandreel -->
+ <target name="octane-mandreel" depends="octane-mandreel-nashorn"/>
+ <target name="octane-mandreel-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.mandreel" runtime="nashorn"/>
</target>
-
<target name="octane-mandreel-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="mandreel"/>
- </antcall>
+ <run-one cond="octane.benchmark.mandreel" runtime="v8"/>
</target>
-
<target name="octane-mandreel-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="mandreel"/>
- </antcall>
+ <run-one cond="octane.benchmark.mandreel" runtime="rhino"/>
</target>
-
<!-- navier-stokes -->
- <target name="octane-navier-stokes" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="navier-stokes"/>
- </antcall>
+ <target name="octane-navier-stokes" depends="octane-navier-stokes-nashorn"/>
+ <target name="octane-navier-stokes-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.navier-stokes" runtime="nashorn"/>
</target>
-
<target name="octane-navier-stokes-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="navier-stokes"/>
- </antcall>
+ <run-one cond="octane.benchmark.navier-stokes" runtime="v8"/>
</target>
-
<target name="octane-navier-stokes-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="navier-stokes"/>
- </antcall>
+ <run-one cond="octane.benchmark.navier-stokes" runtime="rhino"/>
</target>
-
- <!-- pdfjs -->
- <target name="octane-pdfjs" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="pdfjs"/>
- </antcall>
+ <!-- pdfjs -->
+ <target name="octane-pdfjs" depends="octane-pdfjs-nashorn"/>
+ <target name="octane-pdfjs-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.pdfjs" runtime="nashorn"/>
</target>
-
<target name="octane-pdfjs-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="pdfjs"/>
- </antcall>
+ <run-one cond="octane.benchmark.pdfjs" runtime="v8"/>
</target>
-
<target name="octane-pdfjs-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="pdfjs"/>
- </antcall>
+ <run-one cond="octane.benchmark.pdfjs" runtime="rhino"/>
</target>
-
<!-- raytrace -->
- <target name="octane-raytrace" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="raytrace"/>
- </antcall>
+ <target name="octane-raytrace" depends="octane-raytrace-nashorn"/>
+ <target name="octane-raytrace-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.raytrace" runtime="nashorn"/>
</target>
-
<target name="octane-raytrace-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="raytrace"/>
- </antcall>
+ <run-one cond="octane.benchmark.raytrace" runtime="v8"/>
</target>
-
<target name="octane-raytrace-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="raytrace"/>
- </antcall>
+ <run-one cond="octane.benchmark.raytrace" runtime="rhino"/>
</target>
-
<!-- regexp -->
- <target name="octane-regexp" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="regexp"/>
- </antcall>
+ <target name="octane-regexp" depends="octane-regexp-nashorn"/>
+ <target name="octane-regexp-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.regexp" runtime="nashorn"/>
</target>
-
<target name="octane-regexp-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="regexp"/>
- </antcall>
+ <run-one cond="octane.benchmark.regexp" runtime="v8"/>
</target>
-
<target name="octane-regexp-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="regexp"/>
- </antcall>
+ <run-one cond="octane.benchmark.regexp" runtime="rhino"/>
</target>
-
<!-- richards -->
- <target name="octane-richards" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="richards"/>
- </antcall>
+ <target name="octane-richards" depends="octane-richards-nashorn"/>
+ <target name="octane-richards-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.richards" runtime="nashorn"/>
</target>
-
<target name="octane-richards-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="richards"/>
- </antcall>
+ <run-one cond="octane.benchmark.richards" runtime="v8"/>
</target>
-
<target name="octane-richards-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="richards"/>
- </antcall>
+ <run-one cond="octane.benchmark.richards" runtime="rhino"/>
</target>
-
<!-- splay -->
- <target name="octane-splay" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="splay"/>
- </antcall>
+ <target name="octane-splay" depends="octane-splay-nashorn"/>
+ <target name="octane-splay-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.splay" runtime="nashorn"/>
</target>
-
<target name="octane-splay-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-tests" value="splay"/>
- </antcall>
+ <run-one cond="octane.benchmark.splay" runtime="v8"/>
</target>
-
<target name="octane-splay-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="splay"/>
- </antcall>
+ <run-one cond="octane.benchmark.splay" runtime="rhino"/>
</target>
- <!-- splay -->
- <target name="octane-typescript" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="typescript"/>
- </antcall>
+ <!-- typescript -->
+ <target name="octane-typescript" depends="octane-typescript-nashorn"/>
+ <target name="octane-typescript-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.typescript" runtime="nashorn"/>
</target>
-
<target name="octane-typescript-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-typescript" value="typescript"/>
- </antcall>
+ <run-one cond="octane.benchmark.typescript" runtime="v8"/>
</target>
-
<target name="octane-typescript-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="typescript"/>
- </antcall>
+ <run-one cond="octane.benchmark.typescript" runtime="rhino"/>
</target>
<!-- zlib -->
- <target name="octane-zlib" depends="jar">
- <antcall target="run-octane">
- <param name="octane-tests" value="zlib"/>
- </antcall>
+ <target name="octane-zlib" depends="octane-zlib-nashorn"/>
+ <target name="octane-zlib-nashorn" depends="jar">
+ <run-one cond="octane.benchmark.zlib" runtime="nashorn"/>
</target>
-
<target name="octane-zlib-v8" depends="jar">
- <antcall target="run-octane-v8">
- <param name="octane-typescript" value="zlib"/>
- </antcall>
+ <run-one cond="octane.benchmark.zlib" runtime="v8"/>
</target>
-
<target name="octane-zlib-rhino" depends="jar">
- <antcall target="run-octane-rhino">
- <param name="octane-tests" value="zlib"/>
- </antcall>
- </target>
-
- <!-- run octane benchmarks in a single process -->
- <target name="octane-single-process" depends="octane-init">
- <antcall target="run-octane"/>
- </target>
-
- <!-- zlib excluded due to missing implementation of 'read' -->
- <target name="octane-separate-process" depends=
- "octane-box2d, octane-code-load, octane-crypto,
- octane-deltablue, octane-earley-boyer, octane-gbemu,
- octane-mandreel, octane-navier-stokes, octane-pdfjs,
- octane-raytrace, octane-regexp, octane-richards,
- octane-splay, octane-typescript"/>
-
- <target name="--single-process" unless="${octane-test-sys-prop.separate.process}">
- <antcall target="octane-single-process"/>
- </target>
- <target name="--separate-process" if="${octane-test-sys-prop.separate.process}">
- <antcall target="octane-separate-process"/>
- </target>
-
- <!-- run 'octane' in single or separate processes based on config -->
- <target name="octane" depends="init, --single-process, --separate-process"/>
+ <run-one cond="octane.benchmark.zlib" runtime="rhino"/>
+ </target>
+
+ <!--
+ Benchmark runners for one or more benchmarks, single
+ or multiple process
+ -->
+
+ <target name="octane-process-separate" if="${octane-test-sys-prop.separate.process}">
+ <echo message="Running each benchmark in separate processes, starting new JVMs for each."/>
+ <script language="javascript"><![CDATA[
+ var props = [];
+
+ for (var prop in project.getProperties()) {
+ if (prop.startsWith("octane.benchmark.")) {
+ props.push(prop);
+ }
+ }
+
+ //sort benchmark props in alphabetical order by name
+ props.sort(function(a, b) {
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+
+ var runtime = project.getProperty("runtime");
+
+ for (var i in props) {
+ var task = project.createTask("run-one");
+ // workaround for https://issues.apache.org/bugzilla/show_bug.cgi?id=53831, still not fixed
+ if (task.getOwningTarget() == null) {
+ task.setOwningTarget(self.getOwningTarget());
+ }
+ var prop = props[i];
+ task.setDynamicAttribute("cond", prop);
+ task.setDynamicAttribute("runtime", runtime);
+ task.perform();
+ }
+ ]]></script>
+ </target>
+
+ <target name="octane-process-single" unless="${octane-test-sys-prop.separate.process}">
+ <echo message="Running all benchmarks in the same process."/>
+ <pathconvert property="octane.benchmarks" pathsep=" ">
+ <propertyset>
+ <propertyref prefix="octane.benchmark."/>
+ </propertyset>
+ </pathconvert>
+ <antcall target="run-octane${runtime}">
+ <param name="octane-tests" value="${octane.benchmarks}"/>
+ </antcall>
+ </target>
+
+ <!--
+ run 'octane' in single or separate processes based on config
+ This uses nashorn as the default runtime
+ -->
+ <target name="octane-nashorn" depends="jar">
+ <property name="runtime" value="nashorn"/>
+ <antcall target="octane-process-separate"/>
+ <antcall target="octane-process-single"/>
+ </target>
+
+ <!-- alias for 'octane' -->
+ <target name="octane" depends="octane-nashorn"/>
<!-- run octane benchmarks using octane as runtime -->
- <target name="octane-v8" depends="octane-init">
- <antcall target="run-octane-v8"/>
+ <target name="octane-v8" depends="jar">
+ <property name="runtime" value="v8"/>
+ <antcall target="octane-process-separate"/>
+ <antcall target="octane-process-single"/>
</target>
<!-- run octane benchmarks using Rhino as runtime -->
- <target name="octane-rhino" depends="octane-init-rhino">
- <antcall target="run-octane-rhino"/>
- </target>
-
- <target name="run-octane">
+ <target name="octane-rhino" depends="jar">
+ <property name="runtime" value="rhino"/>
+ <antcall target="octane-process-separate"/>
+ <antcall target="octane-process-single"/>
+ </target>
+
+ <macrodef name="run-one">
+ <attribute name="cond"/>
+ <attribute name="runtime" default=""/>
+ <sequential>
+ <antcall target="run-octane-@{runtime}" if:set="@{cond}">
+ <param name="octane-tests" value="${@{cond}}"/>
+ </antcall>
+ </sequential>
+ </macrodef>
+
+ <target name="run-octane-nashorn">
<java classname="${nashorn.shell.tool}"
classpath="${run.test.classpath}"
fork="true"
dir=".">
<jvmarg line="${ext.class.path}"/>
<jvmarg line="${run.test.jvmargs.octane} -Xms${run.test.xms} -Xmx${run.test.xmx}"/>
+ <!-- pass on all properties prefixed with 'nashorn' to the runtime -->
+ <syspropertyset>
+ <propertyref prefix="nashorn."/>
+ </syspropertyset>
<arg value="${octane-test-sys-prop.test.js.framework}"/>
+ <arg value="-scripting"/>
<arg value="--"/>
<arg value="${octane-tests}"/>
<arg value="--runtime"/>
- <arg value="Nashorn"/>
+ <arg value="nashorn"/>
<arg value="--verbose"/>
- <arg value="--iterations 8"/>
+ <arg value="--iterations ${octane.iterations}"/>
</java>
</target>
@@ -383,11 +335,11 @@
<exec executable="${v8.shell}">
<arg value="${octane-test-sys-prop.test.js.framework}"/>
<arg value="--"/>
- <arg value="${octane-tests}"/>
+ <arg value="${octane-tests}"/>
<arg value="--runtime"/>
<arg value="v8"/>
<arg value="--verbose"/>
- <arg value="--iterations 8"/>
+ <arg value="--iterations ${octane.iterations}"/>
</exec>
</target>
@@ -397,12 +349,14 @@
fork="true"
dir=".">
<jvmarg line="${run.test.jvmargs.octane} -Xms${run.test.xms} -Xmx${run.test.xmx}"/>
+ <arg value="-opt"/>
+ <arg value="9"/>
<arg value="${octane-test-sys-prop.test.js.framework}"/>
<arg value="${octane-tests}"/>
<arg value="--runtime"/>
- <arg value="Rhino"/>
+ <arg value="rhino"/>
<arg value="--verbose"/>
- <arg value="--iterations 8"/>
+ <arg value="--iterations ${octane.iterations}"/>
</java>
</target>
@@ -413,18 +367,22 @@
<arg value="${octane-tests}/"/>
</exec>
</target>
-
+
<target name="sunspider-init" depends="jar">
<fileset id="sunspider-set"
- dir="${sunspider-test-sys-prop.test.js.roots}"
- excludes="${sunspider-test-sys-prop.test.js.exclude.list}">
+ dir="${sunspider-test-sys-prop.test.js.roots}"
+ excludes="${sunspider-test-sys-prop.test.js.exclude.list}">
<include name="**/*.js"/>
</fileset>
<pathconvert pathsep=" " property="sunspider-tests" refid="sunspider-set"/>
</target>
+ <!--- SUNSPIDER JOB BELOW -->
+
<!-- run sunspider with Nashorn -->
- <target name="sunspider" depends="sunspider-init">
+ <target name="sunspider" depends="sunspider-nashorn"/>
+
+ <target name="sunspider-nashorn" depends="sunspider-init">
<java classname="${nashorn.shell.tool}"
classpath="${run.test.classpath}"
fork="true"
@@ -436,6 +394,9 @@
<arg value="${sunspider-test-sys-prop.test.js.framework}"/>
<arg value="--"/>
<arg value="${sunspider-tests}/"/>
+ <arg value="--verbose"/>
+ <arg value="--times"/>
+ <arg value="${sunspider.iterations}"/>
</java>
</target>
@@ -445,6 +406,9 @@
<arg value="${sunspider-test-sys-prop.test.js.framework}"/>
<arg value="--"/>
<arg value="${sunspider-tests}/"/>
+ <arg value="--verbose"/>
+ <arg value="--times"/>
+ <arg value="${sunspider.iterations}"/>
</exec>
</target>
@@ -455,8 +419,13 @@
fork="true"
dir=".">
<jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+ <arg value="-opt"/>
+ <arg value="9"/>
<arg value="${sunspider-test-sys-prop.test.js.framework}"/>
<arg value="${sunspider-tests}/"/>
+ <arg value="--verbose"/>
+ <arg value="--times"/>
+ <arg value="${sunspider.iterations}"/>
</java>
</target>
diff --git a/make/build-nasgen.xml b/make/build-nasgen.xml
index 9dca5505..862a1999 100644
--- a/make/build-nasgen.xml
+++ b/make/build-nasgen.xml
@@ -25,7 +25,7 @@
<description>Builds and runs nasgen.</description>
<import file="build.xml"/>
- <target name="build-nasgen" depends="compile-asm">
+ <target name="build-nasgen" depends="prepare">
<ant inheritAll="false" dir="${basedir}/buildtools/nasgen"
antfile="build.xml" target="jar"/>
</target>
@@ -36,11 +36,13 @@
<pathelement location="${basedir}/jcov2/lib/jcov_j2se_rt.jar"/>
<pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/>
<pathelement path="${basedir}/build/classes"/>
+ <pathelement location="${dist.dir}/nasgen.jar"/>
+ <pathelement path="${build.dir}/classes"/>
</classpath>
<jvmarg value="-Djava.ext.dirs="/>
- <arg value="${basedir}/build/classes"/>
+ <arg value="${build.dir}/classes"/>
<arg value="jdk.nashorn.internal.objects"/>
- <arg value="${basedir}/build/classes"/>
+ <arg value="${build.dir}/classes"/>
</java>
</target>
diff --git a/make/build.xml b/make/build.xml
index 3b30a089..a7539f48 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!--
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -21,19 +22,22 @@
or visit www.oracle.com if you need additional information or have any
questions.
-->
+
<project name="nashorn" default="test" basedir="..">
<import file="build-nasgen.xml"/>
- <import file="build-benchmark.xml"/>
<import file="code_coverage.xml"/>
-
<target name="init-conditions">
<!-- loading locally defined resources and properties. NB they owerwrite default ones defined later -->
<property file="${user.home}/.nashorn.project.local.properties"/>
<loadproperties srcFile="make/project.properties"/>
+ <path id="dist.path">
+ <pathelement location="${dist.dir}"/>
+ </path>
<path id="nashorn.ext.path">
<pathelement location="${dist.dir}"/>
+ <pathelement location="${java.ext.dirs}"/>
</path>
<property name="ext.class.path" value="-Djava.ext.dirs=&quot;${toString:nashorn.ext.path}&quot;"/>
<condition property="svn.executable" value="/usr/local/bin/svn" else="svn">
@@ -45,13 +49,11 @@
<condition property="git.executable" value="/usr/local/bin/git" else="git">
<available file="/usr/local/bin/git"/>
</condition>
- <!-- check if JDK already has ASM classes -->
- <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/>
<!-- check if testng.jar is avaiable -->
<available property="testng.available" file="${file.reference.testng.jar}"/>
<!-- check if Jemmy ang testng.jar are avaiable -->
<condition property="jemmy.jfx.testng.available" value="true">
- <and>
+ <and>
<available file="${file.reference.jemmyfx.jar}"/>
<available file="${file.reference.jemmycore.jar}"/>
<available file="${file.reference.jemmyawtinput.jar}"/>
@@ -69,13 +71,39 @@
<condition property="exclude.list" value="./exclude/exclude_list_cc.txt" else="./exclude/exclude_list.txt">
<istrue value="${make.code.coverage}" />
</condition>
+
+ <condition property="jfr.options" value="${run.test.jvmargs.jfr}" else="">
+ <istrue value="${jfr}"/>
+ </condition>
+ </target>
+
+ <!-- check minimum ant version required to be 1.8.4 -->
+ <target name="check-ant-version">
+ <property name="ant.version.required" value="1.8.4"/>
+ <antversion property="ant.current.version" />
+ <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.8.4 or above.">
+ <condition>
+ <not>
+ <antversion atleast="${ant.version.required}"/>
+ </not>
+ </condition>
+ </fail>
</target>
- <target name="init" depends="init-conditions, init-cc">
+ <target name="check-java-version">
+ <!-- look for a Class that is available only in jdk1.8 or above -->
+ <!-- core/exposed API class is better than an implementation class -->
+ <available property="jdk1.8+" classname="java.util.stream.Stream"/>
+ <!-- need jdk1.8 or above -->
+ <fail message="Unsupported Java version: ${ant.java.version}. Please use Java version 1.8 or greater." unless="jdk1.8+">
+ </fail>
+ </target>
+
+ <target name="init" depends="check-ant-version, check-java-version, init-conditions, init-cc">
<!-- extends jvm args -->
- <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs}"/>
- <property name="run.test.jvmargs.octane" value="${run.test.jvmargs.octane.main} ${run.test.cc.jvmargs}" />
+ <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
+ <property name="run.test.jvmargs.octane" value="${run.test.jvmargs.octane.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
<echo message="run.test.jvmargs=${run.test.jvmargs}"/>
<echo message="run.test.jvmargs.octane=${run.test.jvmargs.octane}"/>
@@ -100,19 +128,7 @@
<delete dir="${dist.dir}"/>
</target>
- <!-- do it only if ASM is not available -->
- <target name="compile-asm" depends="prepare" unless="asm.available">
- <javac srcdir="${jdk.asm.src.dir}"
- destdir="${build.classes.dir}"
- excludes="**/optimizer/* **/xml/* **/attrs/*"
- source="${javac.source}"
- target="${javac.target}"
- debug="${javac.debug}"
- encoding="${javac.encoding}"
- includeantruntime="false"/>
- </target>
-
- <target name="compile" depends="compile-asm" description="Compiles nashorn">
+ <target name="compile" depends="prepare" description="Compiles nashorn">
<javac srcdir="${src.dir}"
destdir="${build.classes.dir}"
classpath="${javac.classpath}"
@@ -122,8 +138,7 @@
encoding="${javac.encoding}"
includeantruntime="false" fork="true">
<compilerarg value="-J-Djava.ext.dirs="/>
- <compilerarg value="-Xlint:unchecked"/>
- <compilerarg value="-Xlint:deprecation"/>
+ <compilerarg value="-Xlint:all"/>
<compilerarg value="-XDignore.symbol.file"/>
<compilerarg value="-Xdiags:verbose"/>
</javac>
@@ -140,6 +155,7 @@
<fileset dir="${src.dir}/jdk/nashorn/tools/resources/"/>
</copy>
<copy file="${src.dir}/jdk/internal/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/internal/dynalink/support"/>
+ <copy file="${src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${build.classes.dir}/jdk/nashorn/internal/codegen"/>
<echo message="full=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
<echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
@@ -291,6 +307,10 @@
<target name="generate-policy-file" depends="prepare">
<echo file="${build.dir}/nashorn.policy">
+grant codeBase "file:/${toString:dist.path}/nashorn.jar" {
+ permission java.security.AllPermission;
+};
+
grant codeBase "file:/${basedir}/${nashorn.internal.tests.jar}" {
permission java.security.AllPermission;
};
@@ -298,6 +318,14 @@ grant codeBase "file:/${basedir}/${nashorn.internal.tests.jar}" {
grant codeBase "file:/${basedir}/${file.reference.testng.jar}" {
permission java.security.AllPermission;
};
+//// in case of absolute path:
+grant codeBase "file:/${nashorn.internal.tests.jar}" {
+ permission java.security.AllPermission;
+};
+
+grant codeBase "file:/${file.reference.testng.jar}" {
+ permission java.security.AllPermission;
+};
grant codeBase "file:/${basedir}/test/script/trusted/*" {
permission java.security.AllPermission;
@@ -322,6 +350,13 @@ grant codeBase "file:/${basedir}/test/script/basic/parser/*" {
permission java.util.PropertyPermission "nashorn.test.*", "read";
};
+grant codeBase "file:/${basedir}/test/script/basic/es6/*" {
+ permission java.io.FilePermission "${basedir}/test/script/-", "read";
+ permission java.io.FilePermission "$${user.dir}", "read";
+ permission java.util.PropertyPermission "user.dir", "read";
+ permission java.util.PropertyPermission "nashorn.test.*", "read";
+};
+
grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" {
permission java.util.PropertyPermission "java.security.policy", "read";
};
@@ -330,6 +365,10 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
permission java.lang.RuntimePermission "nashorn.JavaReflection";
};
+grant codeBase "file:/${basedir}/test/script/markdown.js" {
+ permission java.io.FilePermission "${basedir}/test/script/external/showdown/-", "read";
+};
+
</echo>
<replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Windows - to make URLs with normal path separators -->
@@ -345,6 +384,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<available file="${test.external.dir}/yui" property="test-sys-prop.external.yui"/>
<available file="${test.external.dir}/jquery" property="test-sys-prop.external.jquery"/>
<available file="${test.external.dir}/test262" property="test-sys-prop.external.test262"/>
+ <available file="${test.external.dir}/showdown" property="test-sys-prop.external.markdown"/>
</target>
<target name="check-testng" unless="testng.available">
@@ -377,10 +417,11 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<fileset id="test.nosecurity.classes" dir="${build.test.classes.dir}">
<include name="**/framework/ScriptTest.class"/>
</fileset>
- <testng outputdir="${build.nosecurity.test.results.dir}" classfilesetref="test.nosecurity.classes"
+ <testng outputdir="${build.nosecurity.test.results.dir}/${testResultsSubDir}" classfilesetref="test.nosecurity.classes"
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
<jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
+ <sysproperty key="nashorn.jar" value="${dist.dir}/nashorn.jar"/>
<propertyset>
<propertyref prefix="nashorn."/>
</propertyset>
@@ -388,6 +429,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<propertyref prefix="test-sys-prop-no-security."/>
<mapper from="test-sys-prop-no-security.*" to="*" type="glob"/>
</propertyset>
+ <sysproperty key="optimistic.override" value="${optimistic}"/>
<classpath>
<pathelement path="${run.test.classpath}"/>
</classpath>
@@ -398,15 +440,19 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<target name="-test-security">
<delete dir="${build.dir}/nashorn_code_cache"/>
<property name="debug.test.jvmargs" value=""/>
- <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
- verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
+ <testng outputdir="${build.test.results.dir}/${testResultsSubDir}" classfilesetref="test.classes"
+ verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
<jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
<jvmarg line="${debug.test.jvmargs}"/>
<propertyset>
+ <propertyref prefix="nashorn."/>
+ </propertyset>
+ <propertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</propertyset>
+ <sysproperty key="optimistic.override" value="${optimistic}"/>
<sysproperty key="test.js.excludes.file" value="${exclude.list}"/>
<classpath>
<pathelement path="${run.test.classpath}"/>
@@ -414,18 +460,30 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
</testng>
</target>
- <target name="test" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file, -test-security, -test-nosecurity" if="testng.available"/>
+ <target name="test" depends="test-pessimistic, test-optimistic"/>
- <target name="test-basicparallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file">
- <!-- use just build.test.classes.dir to avoid referring to TestNG -->
- <java classname="${parallel.test.runner}" dir="${basedir}" classpath="${build.test.classes.dir}" failonerror="true" fork="true">
- <jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
- <syspropertyset>
- <propertyref prefix="test-sys-prop."/>
- <mapper type="glob" from="test-sys-prop.*" to="*"/>
- </syspropertyset>
- </java>
+ <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <echo message="Running test suite in OPTIMISTIC mode..."/>
+ <antcall target="-test-nosecurity" inheritRefs="true">
+ <param name="optimistic" value="true"/>
+ <param name="testResultsSubDir" value="optimistic"/>
+ </antcall>
+ <antcall target="-test-security" inheritRefs="true">
+ <param name="optimistic" value="true"/>
+ <param name="testResultsSubDir" value="optimistic"/>
+ </antcall>
+ </target>
+
+ <target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <echo message="Running test suite in PESSIMISTIC mode..."/>
+ <antcall target="-test-nosecurity" inheritRefs="true">
+ <param name="optimistic" value="false"/>
+ <param name="testResultsSubDir" value="pessimistic"/>
+ </antcall>
+ <antcall target="-test-security" inheritRefs="true">
+ <param name="optimistic" value="false"/>
+ <param name="testResultsSubDir" value="pessimistic"/>
+ </antcall>
</target>
<target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available">
@@ -436,19 +494,19 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
</fileset>
-
+
<copy file="${file.reference.jfxrt.jar}" todir="dist"/>
-
+
<condition property="jfx.prism.order" value="-Dprism.order=j2d" else=" ">
- <not>
+ <not>
<os family="mac"/>
</not>
- </condition>
-
+ </condition>
+
<testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
<jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
<propertyset>
<propertyref prefix="testjfx-test-sys-prop."/>
<mapper from="testjfx-test-sys-prop.*" to="*" type="glob"/>
@@ -459,7 +517,26 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
</classpath>
</testng>
</target>
-
+
+ <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <fileset id="test.classes" dir="${build.test.classes.dir}">
+ <include name="**/framework/*Test.class"/>
+ </fileset>
+
+ <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
+ verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
+ <jvmarg line="${ext.class.path}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+ <propertyset>
+ <propertyref prefix="testmarkdown-test-sys-prop."/>
+ <mapper from="testmarkdown-test-sys-prop.*" to="*" type="glob"/>
+ </propertyset>
+ <classpath>
+ <pathelement path="${run.test.classpath}"/>
+ </classpath>
+ </testng>
+ </target>
+
<target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
@@ -468,7 +545,10 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
<jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+ <propertyset>
+ <propertyref prefix="nashorn."/>
+ </propertyset>
<propertyset>
<propertyref prefix="test262-test-sys-prop."/>
<mapper from="test262-test-sys-prop.*" to="*" type="glob"/>
@@ -485,7 +565,9 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<!-- use just build.test.classes.dir to avoid referring to TestNG -->
<java classname="${parallel.test.runner}" dir="${basedir}" fork="true">
<jvmarg line="${ext.class.path}"/>
- <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+ <!-- avoid too many typeinfo cache files. Each script is run only once anyway -->
+ <jvmarg line="-Dnashorn.typeInfo.disabled=true"/>
<classpath>
<pathelement path="${run.test.classpath}"/>
</classpath>
@@ -496,6 +578,26 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
</java>
</target>
+ <target name="testparallel" depends="test-parallel"/>
+
+ <target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <!-- use just build.test.classes.dir to avoid referring to TestNG -->
+ <java classname="${parallel.test.runner}" dir="${basedir}"
+ failonerror="true"
+ fork="true">
+ <jvmarg line="${ext.class.path}"/>
+ <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+ <classpath>
+ <pathelement path="${run.test.classpath}"/>
+ <pathelement path="${build.test.classes.dir}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper type="glob" from="test-sys-prop.*" to="*"/>
+ </syspropertyset>
+ </java>
+ </target>
+
<target name="all" depends="test, docs"
description="Build, test and generate docs for nashorn"/>
@@ -529,6 +631,8 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<!-- clone test262 git repo -->
<exec executable="${git.executable}">
<arg value="clone"/>
+ <arg value="--branch"/>
+ <arg value="es5-tests"/>
<arg value="https://github.com/tc39/test262"/>
<arg value="${test.external.dir}/test262"/>
</exec>
@@ -604,6 +708,11 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<get src="http://yui.yahooapis.com/3.5.1/build/yui/yui.js" dest="${test.external.dir}/yui" skipexisting="true" ignoreerrors="true"/>
<get src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js" dest="${test.external.dir}/yui" skipexisting="true" ignoreerrors="true"/>
+ <!-- showdown -->
+ <mkdir dir="${test.external.dir}/showdown"/>
+ <get src="https://raw.github.com/coreyti/showdown/master/src/showdown.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+ <get src="https://raw.github.com/coreyti/showdown/master/src/extensions/table.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+
</target>
<!-- update external test suites that are pulled from source control systems -->
@@ -619,4 +728,6 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<target name="alltests" depends="exit-if-no-testng, externals, update-externals, test, test262parallel, perf"/>
+ <import file="build-benchmark.xml"/>
+
</project>
diff --git a/make/nbproject/ide-targets.xml b/make/nbproject/ide-targets.xml
index 70b3e68f..d1e8135f 100644
--- a/make/nbproject/ide-targets.xml
+++ b/make/nbproject/ide-targets.xml
@@ -31,9 +31,10 @@
<classpath path="${run.test.classpath}"/>
</nbjpdastart>
<java classname="jdk.nashorn.tools.Shell" classpath="${run.test.classpath}" dir="samples" fork="true">
+ <jvmarg line="-Dnashorn.optimistic"/>
<jvmarg line="${ext.class.path}"/>
<jvmarg line="${run.test.jvmargs}"/>
- <arg value="test.js"/>
+ <arg value="../samples/test.js"/>
<jvmarg value="-Xdebug"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
</java>
diff --git a/make/project.properties b/make/project.properties
index 2abccdeb..9d36fbdc 100644
--- a/make/project.properties
+++ b/make/project.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,7 @@ parallel.test.runner=jdk.nashorn.internal.test.framework.ParallelTestRunner
# test classes directory
build.test.classes.dir=${build.dir}/test/classes
+
# nashorn test jar - internal tests jar and api tests jar
nashorn.internal.tests.jar=${build.dir}/nashorn-internal-tests.jar
nashorn.api.tests.jar=${build.dir}/nashorn-api-tests.jar
@@ -60,6 +61,7 @@ nashorn.api.tests.jar=${build.dir}/nashorn-api-tests.jar
# test results directory
build.test.results.dir=${build.dir}/test/reports
build.nosecurity.test.results.dir=${build.dir}/test/nosecurity/reports
+build.nooptimistic.test.results.dir=${build.dir}/test/nooptimistic/reports
# This directory is removed when the project is cleaned:
dist.dir=dist
@@ -72,6 +74,9 @@ fxshell.classes.dir = ${build.dir}/fxshell/classes
fxshell.dir = tools/fxshell
fxshell.jar = ${dist.dir}/nashornfx.jar
+# configuration for java flight recorder
+run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
+
# jars refererred
file.reference.testng.jar=test/lib/testng.jar
@@ -122,6 +127,7 @@ test.external.dir=test/script/external
test262.dir=${test.external.dir}/test262
test262.suite.dir=${test262.dir}/test/suite
testjfx.dir=${test.script.dir}/jfx
+testmarkdown.dir=${test.script.dir}/markdown
test-sys-prop.test.dir=${test.dir}
test-sys-prop.test.js.roots=${test.basic.dir} ${test.maptests.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
@@ -163,21 +169,14 @@ test-sys-prop.test.js.unchecked.dir=${test262.dir}
# test root for octane
octane-test-sys-prop.test.js.roots=${test.external.dir}/octane/
-# run octane benchmars in separate processes?
+# run octane benchmars in separate processes? (recommended)
octane-test-sys-prop.separate.process=true
# framework root for octane
octane-test-sys-prop.test.js.framework=${test.basic.dir}/run-octane.js
-# list of tests to be excluded
-# mandreel excluded due to OOM
-octane-test-sys-prop.test.js.exclude.list=\
- base.js \
- run.js \
- mandreel.js
-
# test root for sunspider
-sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0/
+sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0.2/
# framework root for sunspider
sunspider-test-sys-prop.test.js.framework=${test.basic.dir}/runsunspider.js
@@ -193,6 +192,7 @@ test262-test-sys-prop.test.js.shared.context=true
# test262 test root
test262-test-sys-prop.test.js.roots=${test262.suite.dir}
+
# test262 enable/disable strict mode tests
test262-test-sys-prop.test.js.enable.strict.mode=true
@@ -202,7 +202,7 @@ test262-test-sys-prop.test.js.enable.strict.mode=true
# list of test262 test dirs to be excluded
test262-test-sys-prop.test.js.exclude.dir=\
${test262.suite.dir}/intl402/ \
- ${test262.suite.dir}/bestPractice/
+ ${test262.suite.dir}/bestPractice/
test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests
@@ -216,8 +216,18 @@ test262-test-sys-prop.test.js.framework=\
${test262.dir}/test/harness/framework.js \
${test262.dir}/test/harness/sta.js
+# testmarkdown test root
+testmarkdown-test-sys-prop.test.js.roots=${testmarkdown.dir}
+
+# execute testmarkdown tests in shared nashorn context or not?
+testmarkdown-test-sys-prop.test.js.shared.context=false
+
+# framework root for markdown script tests
+testmarkdown-test-sys-prop.test.js.framework=\
+ ${test.script.dir}${file.separator}markdown.js
+
# testjfx test root
-testjfx-test-sys-prop.test.js.roots=${testjfx.dir}
+testjfx-test-sys-prop.test.js.roots=${testjfx.dir}
# execute testjfx tests in shared nashorn context or not?
testjfx-test-sys-prop.test.js.shared.context=false
@@ -254,48 +264,131 @@ test.src.dir=test/src
run.test.xmx=2G
run.test.xms=2G
+# uncomment this jfr.args to enable light recordings. the stack needs to be cranked up to 1024 frames,
+# or everything will as of the now drown in lambda forms and be cut off.
+#
+#jfr.args=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath="test_suite.jfr",stackdepth=1024 \
+
+jfr.args=
+
run.test.user.language=tr
run.test.user.country=TR
-run.test.jvmargs.common=-server -XX:+TieredCompilation -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError
-
-#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M
-# -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods
+run.test.jvmargs.common=\
+ -server \
+ -Dfile.encoding=UTF-8 \
+ -Duser.language=${run.test.user.language} \
+ -Duser.country=${run.test.user.country} \
+ -Dnashorn.typeInfo.cacheDir=${build.dir}${file.separator}test${file.separator}type_info_cache \
+ ${jfr.args} \
+ -XX:+HeapDumpOnOutOfMemoryError
# turn on assertions for tests
run.test.jvmargs.main=${run.test.jvmargs.common} -ea
-#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M
-run.test.jvmargs.octane.main=${run.test.jvmargs.common}
+# Extra jvmargs that might be useful for debugging
+# and performance improvements/monitoring
+#
+# -XX:+UnlockDiagnosticVMOptions
+#
+# turn off compressed class pointers in metaspace
+# -XX:-UseCompressedKlassPointers
+#
+# dump the heap after every GC
+# -XX:+PrintHeapAtGC
+#
+# manually set a metaspace size for class data
+# -XX:ClassMetaspaceSize=300M
+#
+# print out methods compiled
+# -XX:+PrintCompilation
+#
+# print all compiled nmethods with oopmaps and lots of other info
+# -XX:+PrintNMethods
+#
+# activate the generic "UseNewCode" flag to test whatever functionality
+# lies behind it. This is the preferred way to test a, yet flagless,
+# feature in HotSpot - for example, the uncommon trap placement fix
+# was hidden behind this flag before it became the default
+#
+# -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode
+#
+# Crank up the type profile level to 222, which has some warmup
+# penalties, but produces much better code for JavaScript, where better
+# and more intrusive type profiling is required to get rid of
+# a large amount of unnecessary guard code, that could not otherwise
+# be eliminated
+#
+# -XX:TypeProfileLevel=222
+#
+
+# Use best known performance options for octane
+run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:TypeProfileLevel=222
-run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
+# Security manager args - make sure that we run with the nashorn.policy that the build creates
+run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy
# VM options for script tests with @fork option
test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}
# path of rhino.jar for benchmarks
-rhino.jar=
+rhino.dir=
+rhino.jar=${rhino.dir}/js.jar
v8.shell=d8
+# How many iterations should 'ant octane' run for each
+# benchmark
+octane.iterations=25
+
+# List of octane tests to run, as properties prefixed with
+# "octane.benchmark." mapping to the benchmark name in
+# the test harness
+#
+# Octane tests that are disabled should have their entire line
+# commented out Tests may be disabled for functionality reasons when
+# they have bugs or when the runtime doesn't handle them (yet)
+octane.benchmark.box2d=box2d
+#octane.benchmark.code-load=code-load
+octane.benchmark.crypto=crypto
+octane.benchmark.deltablue=deltablue
+octane.benchmark.earley-boyer=earley-boyer
+octane.benchmark.gbemu=gbemu
+octane.benchmark.navier-stokes=navier-stokes
+octane.benchmark.mandreel=mandreel
+octane.benchmark.pdfjs=pdfjs
+octane.benchmark.raytrace=raytrace
+octane.benchmark.regexp=regexp
+octane.benchmark.richards=richards
+octane.benchmark.splay=splay
+#octane.benchmark.typescript=typescript
+#octane.benchmark.zlib=zlib
+
#path to rhino jar file
octaneperf-sys-prop.rhino.jar=${rhino.jar}
#timeout for performance tests in minutes
octaneperf-sys-prop.timeout.value=10
-################
-# codecoverage #
-################
- #enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties
+#how many iterations to run sunspider after warmup
+sunspider.iterations=3000
+
+#################
+# code coverage #
+#################
+
+#enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties
make.code.coverage=false
- #type of codecoverage; one of static or dynamic. Now only dynamic is supported
+
+#type of codecoverage; one of static or dynamic. Now only dynamic is supported
jcov=dynamic
- #naming of CC results
- #NB directory specified in the cc.dir will be cleaned up!!!
+
+#naming of CC results
+#NB directory specified in the cc.dir will be cleaned up!!!
cc.dir=${basedir}/../Codecoverage_Nashorn
cc.result.file.name=CC_${jcov}_nashorn.xml
- #dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties
+
+#dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties
jcov2.lib.dir=${basedir}/../jcov2/lib
jcov.jar=${jcov2.lib.dir}/jcov.jar
cc.include=jdk\.nashorn\.*
diff --git a/samples/BufferArray.java b/samples/BufferArray.java
index 00d66023..b26b5c08 100644
--- a/samples/BufferArray.java
+++ b/samples/BufferArray.java
@@ -29,8 +29,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import jdk.nashorn.api.scripting.AbstractJSObject;
import java.nio.DoubleBuffer;
+import jdk.nashorn.api.scripting.AbstractJSObject;
/**
* Simple class demonstrating pluggable script object
@@ -52,41 +52,49 @@ public class BufferArray extends AbstractJSObject {
// underlying nio buffer
private final DoubleBuffer buf;
- public BufferArray(int size) {
+ /**
+ * Constructor
+ * @param size initial size
+ */
+ public BufferArray(final int size) {
buf = DoubleBuffer.allocate(size);
}
- public BufferArray(DoubleBuffer buf) {
+ /**
+ * Constructur
+ * @param buf {@link DoubleBuffer} to link to
+ */
+ public BufferArray(final DoubleBuffer buf) {
this.buf = buf;
}
// called to check if indexed property exists
@Override
- public boolean hasSlot(int index) {
+ public boolean hasSlot(final int index) {
return index > 0 && index < buf.capacity();
}
// get the value from that index
@Override
- public Object getSlot(int index) {
+ public Object getSlot(final int index) {
return buf.get(index);
}
// set the value at that index
@Override
- public void setSlot(int index, Object value) {
+ public void setSlot(final int index, final Object value) {
buf.put(index, ((Number)value).doubleValue());
}
// do you have a property of that given name?
@Override
- public boolean hasMember(String name) {
+ public boolean hasMember(final String name) {
return "length".equals(name) || "buf".equals(name);
}
// get the value of that named property
@Override
- public Object getMember(String name) {
+ public Object getMember(final String name) {
switch (name) {
case "length":
return buf.capacity();
@@ -94,7 +102,7 @@ public class BufferArray extends AbstractJSObject {
// return a 'function' value for this property
return new AbstractJSObject() {
@Override
- public Object call(Object thiz, Object... args) {
+ public Object call(final Object thiz, final Object... args) {
return BufferArray.this.buf;
}
@@ -104,6 +112,8 @@ public class BufferArray extends AbstractJSObject {
return true;
}
};
+ default:
+ break;
}
return null;
}
diff --git a/samples/array_mapreduce.js b/samples/array_mapreduce.js
index 5335f35d..32184e9c 100644
--- a/samples/array_mapreduce.js
+++ b/samples/array_mapreduce.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,9 +31,9 @@
// Usage: jjs array_mapreduce.js
-// Many Array.prototype functions such as map,
+// Many Array.prototype functions such as map,
// filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as
+// These functions accept ECMAScript array as well as
// many array-like objects including java arrays.
// So, you can do map/filter/reduce with Java streams or
// you can also use Array.prototype functions as below.
@@ -73,6 +73,6 @@ forEach.call(jarr, function(x) print(x));
// print sum of squares of the random numbers
print("Square sum:",
reduce.call(
- map.call(jarr, function(x) x*x),
+ map.call(jarr, function(x) x*x),
function(x, y) x + y)
);
diff --git a/samples/astviewer.js b/samples/astviewer.js
index 090e50ee..ad70d91d 100644
--- a/samples/astviewer.js
+++ b/samples/astviewer.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -82,7 +82,7 @@ var sourceName = arguments.length == 0? __FILE__ : arguments[0];
// load parser.js from nashorn resources
load("nashorn:parser.js");
-// read the full content of the file and parse it
+// read the full content of the file and parse it
// to get AST of the script specified
var ast = parse(readFully(sourceName));
diff --git a/samples/barchart_weather.js b/samples/barchart_weather.js
index 8574f0a2..9402682f 100644
--- a/samples/barchart_weather.js
+++ b/samples/barchart_weather.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/browser_dom.js b/samples/browser_dom.js
new file mode 100644
index 00000000..94324c7a
--- /dev/null
+++ b/samples/browser_dom.js
@@ -0,0 +1,91 @@
+#// Usage: jjs -fx browser.js
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!$OPTIONS._fx) {
+ print("Usage: jjs -fx browser.js");
+ exit(1);
+}
+
+// JavaFX classes used
+var ChangeListener = Java.type("javafx.beans.value.ChangeListener");
+var Scene = Java.type("javafx.scene.Scene");
+var WebView = Java.type("javafx.scene.web.WebView");
+var EventListener = Java.type("org.w3c.dom.events.EventListener");
+
+// JavaFX start method
+function start(stage) {
+ start.title = "Web View";
+ var wv = new WebView();
+ wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+This is the title
+</title>
+<script>
+// click count for OK button
+var okCount = 0;
+</script>
+</head>
+<body>
+Button from the input html<br>
+<button type="button" onclick="okCount++">OK</button><br>
+</body>
+</html>
+EOF, "text/html");
+
+ // attach onload handler
+ wv.engine.loadWorker.stateProperty().addListener(
+ new ChangeListener() {
+ changed: function() {
+ // DOM document element
+ var document = wv.engine.document;
+ // DOM manipulation
+ var btn = document.createElement("button");
+ var n = 0;
+ // attach a button handler - nashorn function!
+ btn.onclick = new EventListener(function() {
+ n++; print("You clicked " + n + " time(s)");
+ print("you clicked OK " + wv.engine.executeScript("okCount"));
+ });
+ // attach text to button
+ var t = document.createTextNode("Click Me!");
+ btn.appendChild(t);
+ // attach button to the document
+ document.body.appendChild(btn);
+ }
+ }
+ );
+ stage.scene = new Scene(wv, 750, 500);
+ stage.show();
+}
diff --git a/samples/call_lambda.js b/samples/call_lambda.js
index d865164f..c5a4dc66 100644
--- a/samples/call_lambda.js
+++ b/samples/call_lambda.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/counters.js b/samples/counters.js
index d89ad581..4a570b02 100644
--- a/samples/counters.js
+++ b/samples/counters.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/dirname.js b/samples/dirname.js
index 119d4f33..bb9279d0 100644
--- a/samples/dirname.js
+++ b/samples/dirname.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/disassemble.js b/samples/disassemble.js
index 654b9dd8..7cf501ff 100644
--- a/samples/disassemble.js
+++ b/samples/disassemble.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -33,7 +33,7 @@
// Simple .class disassembler that uses bundled ObjectWeb ASM
// classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are
-// not part of official jdk8 API. It can be changed/removed
+// not part of official jdk8 API. It can be changed/removed
// without notice. So, this script is brittle by design!
// This example demonstrates passing arguments to script
diff --git a/samples/engine/accessvar.js b/samples/engine/accessvar.js
index ae9ec7de..abd54862 100644
--- a/samples/engine/accessvar.js
+++ b/samples/engine/accessvar.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/engine/callfunc.js b/samples/engine/callfunc.js
index 76108fd1..e177a7b9 100644
--- a/samples/engine/callfunc.js
+++ b/samples/engine/callfunc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -29,7 +29,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// simple example showing how to call a global script
+// simple example showing how to call a global script
// function from caller
var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
@@ -42,7 +42,7 @@ var engine = manager.getEngineByName("js");
engine.eval("function func(name) { print('I am func, hello ' + name) }");
// invoke functions, methods of code evaluated by engine
-// from javax.script.Invocable interface. But, hey,
+// from javax.script.Invocable interface. But, hey,
// calling code is JavaScript and don't worry about types :)
engine.invokeFunction("func", "Nashorn");
diff --git a/samples/engine/callmethod.js b/samples/engine/callmethod.js
index 8199dcd6..c8cbb300 100644
--- a/samples/engine/callmethod.js
+++ b/samples/engine/callmethod.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -55,7 +55,7 @@ engine.eval(<<CODE
CODE);
// invoke methods of an object in script world
-// from javax.script.Invocable interface. But, hey,
+// from javax.script.Invocable interface. But, hey,
// calling code is JavaScript and don't worry about types :)
// get that script object on which to call a method
diff --git a/samples/engine/exposevar.js b/samples/engine/exposevar.js
index 93f57ed8..f1a309c8 100644
--- a/samples/engine/exposevar.js
+++ b/samples/engine/exposevar.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/engine/foreignobject.js b/samples/engine/foreignobject.js
index 3850089d..930c3e85 100644
--- a/samples/engine/foreignobject.js
+++ b/samples/engine/foreignobject.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -54,7 +54,7 @@ CODE);
// the class jdk.nashorn.api.scripting.ScriptObjectMirror
// But nashorn's dynalink linker can treat these objects
// specially to support natural script syntax to access..
-// In Java code, you need to use ScriptObjectMirror's
+// In Java code, you need to use ScriptObjectMirror's
// methods though. Once again, script world is simpler :-)
var foreignObj = engine.get("obj");
diff --git a/samples/engine/hello.js b/samples/engine/hello.js
index 37fabbfe..72606cf5 100644
--- a/samples/engine/hello.js
+++ b/samples/engine/hello.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/engine/interface.js b/samples/engine/interface.js
index 75b7aa21..6461776a 100644
--- a/samples/engine/interface.js
+++ b/samples/engine/interface.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -50,7 +50,7 @@ CODE);
// create Java interface object whose methods are
// implemented by script functions. This is from
-// javax.script.Invocable. But we are in JS world,
+// javax.script.Invocable. But we are in JS world,
// don't worry about types :)
var Runnable = Java.type("java.lang.Runnable");
diff --git a/samples/engine/interface2.js b/samples/engine/interface2.js
index 771b1101..508be3ac 100644
--- a/samples/engine/interface2.js
+++ b/samples/engine/interface2.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/engine/lambda_as_func.js b/samples/engine/lambda_as_func.js
index 2600f17a..260eeb95 100644
--- a/samples/engine/lambda_as_func.js
+++ b/samples/engine/lambda_as_func.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/env.js b/samples/env.js
index 74377ebd..1febe7ac 100644
--- a/samples/env.js
+++ b/samples/env.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,8 +31,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// In nashorn -scripting mode,
-// "$ENV" object exposes process
+// In nashorn -scripting mode,
+// "$ENV" object exposes process
// environment variables
print($ENV.PATH);
diff --git a/samples/expression_closure.js b/samples/expression_closure.js
index 1efb1842..17189a8e 100644
--- a/samples/expression_closure.js
+++ b/samples/expression_closure.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/filebrowser.js b/samples/filebrowser.js
index da00553a..2c36275b 100644
--- a/samples/filebrowser.js
+++ b/samples/filebrowser.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/fileline.js b/samples/fileline.js
index 05c99759..59d2288b 100644
--- a/samples/fileline.js
+++ b/samples/fileline.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/find_nonfinals2.js b/samples/find_nonfinals2.js
new file mode 100644
index 00000000..75fde624
--- /dev/null
+++ b/samples/find_nonfinals2.js
@@ -0,0 +1,118 @@
+#// Usage: jjs find_nonfinals2.js -- <directory>
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example finds method
+// parameters without "final" keyword and prints info on those.
+
+if (arguments.length == 0) {
+ print("Usage: jjs find_nonfinals2.js -- <directory>");
+ exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+var Modifier = Java.type("javax.lang.model.element.Modifier");
+
+function checkNonFinalParams(p) {
+ // get the system compiler tool
+ var compiler = ToolProvider.systemJavaCompiler;
+ // get standard file manager
+ var fileMgr = compiler.getStandardFileManager(null, null, null);
+ // Using Java.to convert script array (arguments) to a Java String[]
+ var compUnits = fileMgr.getJavaFileObjects(
+ Java.to(arguments, StringArray));
+ // create a new compilation task
+ var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+ // subclass SimpleTreeVisitor - to find non-final method params
+ var NonFinalsFinder = Java.extend(TreeScanner);
+
+ function printMethod(method) {
+ print(method.modifiers + " "+ method.returnType + " " +
+ method.name + "(" + method.parameters + ")");
+ }
+
+ var pkgName, clsName, compUnitName, lineMap;
+ var visitor = new NonFinalsFinder() {
+ visitCompilationUnit: function(compUnit, p) {
+ pkgName = compUnit.packageName;
+ compUnitName = compUnit.sourceFile.name;
+ lineMap = compUnit.lineMap;
+ return Java.super(visitor).visitCompilationUnit(compUnit, p);
+ },
+
+ visitClass: function(clazz, p) {
+ clsName = clazz.name;
+ return Java.super(visitor).visitClass(clazz, p);
+ },
+
+ visitMethod: function (method, p) {
+ var params = method.parameters;
+ for each (var p in params) {
+ var modifiers = p.modifiers;
+ if (! modifiers.flags.contains(Modifier.FINAL)) {
+ print(compUnitName);
+ print(pkgName + "." + clsName);
+ printMethod(method);
+ print("->", p,
+ " @ " + lineMap.getLineNumber(p.pos) + ":" +
+ lineMap.getColumnNumber(p.pos));
+ }
+ }
+ }
+ }
+
+ for each (var cu in task.parse()) {
+ cu.accept(visitor, null);
+ }
+}
+
+// for each ".java" file in directory (recursively).
+function main(dir) {
+ var totalCount = 0;
+ Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+ forEach(function(p) {
+ var name = p.toFile().absolutePath;
+ if (name.endsWith(".java")) {
+ checkNonFinalParams(p);
+ }
+ });
+}
+
+main(new File(arguments[0]));
diff --git a/samples/fizzbuzz.js b/samples/fizzbuzz.js
index ba8d83d4..a0fde95b 100644
--- a/samples/fizzbuzz.js
+++ b/samples/fizzbuzz.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/for_each.js b/samples/for_each.js
index 10fc39a1..988e659f 100644
--- a/samples/for_each.js
+++ b/samples/for_each.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -42,7 +42,7 @@ var JArray = Java.type("int[]");
var arr = new JArray(10);
// store squares as values
-for (i in arr)
+for (i in arr)
arr[i] = i*i;
// for .. each on java arrays
@@ -57,7 +57,7 @@ var System = Java.type("java.lang.System");
print("System properties");
for each (p in System.properties.entrySet()) {
print(p.key, "=", p.value);
-}
+}
// print process environment vars as name = value pairs
print("Process environment");
diff --git a/samples/gaussian_random.js b/samples/gaussian_random.js
index f52f49f3..235cbcba 100644
--- a/samples/gaussian_random.js
+++ b/samples/gaussian_random.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -37,7 +37,7 @@ var DoubleStream = Java.type("java.util.stream.DoubleStream");
var r = new Random();
// expression closure (see expression_closure.js as well)
-// passed as lambda double generator. "print" passed as
+// passed as lambda double generator. "print" passed as
// double consumer lambda to 'forEach' method.
DoubleStream
diff --git a/samples/gaussian_random_bind.js b/samples/gaussian_random_bind.js
index 052520cd..93f2a17d 100644
--- a/samples/gaussian_random_bind.js
+++ b/samples/gaussian_random_bind.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -34,7 +34,7 @@
var Random = Java.type("java.util.Random");
var DoubleStream = Java.type("java.util.stream.DoubleStream");
-// function as lambda double generator. "print" passed as
+// function as lambda double generator. "print" passed as
// double consumer lambda to 'forEach' method.
// Function.prototype.bind used to attach 'state' for the
// generator function.
diff --git a/samples/gutenberg.js b/samples/gutenberg.js
index 4d83a573..3f21b247 100644
--- a/samples/gutenberg.js
+++ b/samples/gutenberg.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -69,7 +69,7 @@ function readRssFeed(url) {
// capture title, description now
inItem = true;
}
-
+
if (inItem) {
switch (local) {
case 'title':
diff --git a/samples/heredoc.js b/samples/heredoc.js
index 0c52ca93..dd793616 100644
--- a/samples/heredoc.js
+++ b/samples/heredoc.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -38,14 +38,14 @@
var sender = "Buffy the Vampire Slayer";
var recipient = "Spike";
-
+
print(<<END
-
+
Dear ${recipient},
-
+
I wish you to leave Sunnydale and never return.
-
+
Not Quite Love,
${sender}
-
+
END);
diff --git a/samples/interface_impl.js b/samples/interface_impl.js
index 5e498166..f2197665 100644
--- a/samples/interface_impl.js
+++ b/samples/interface_impl.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/javaastviewer.js b/samples/javaastviewer.js
index c446abe5..e8285c08 100644
--- a/samples/javaastviewer.js
+++ b/samples/javaastviewer.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -56,8 +56,8 @@ function javaASTToScriptObject(args) {
// may not be exhaustive - any getAbc would become "abc" property or
// public field becomes a property of same name.
var ignoredProps = new HashSet();
- for each (var word in
- ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs',
+ for each (var word in
+ ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs',
'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam',
'restype', 'params', 'startPosition', 'thrown',
'tree', 'typarams', 'typetag', 'vartype']) {
@@ -83,7 +83,7 @@ function javaASTToScriptObject(args) {
var visitor = new ConverterVisitor() {
// convert java AST node to a friendly script object
- // which can be viewed. Every node ends up in defaultAction
+ // which can be viewed. Every node ends up in defaultAction
// method of SimpleTreeVisitor method.
defaultAction: function (node, p) {
diff --git a/samples/javacastcounter.js b/samples/javacastcounter.js
index 607b2f82..6d569a10 100644
--- a/samples/javacastcounter.js
+++ b/samples/javacastcounter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -83,7 +83,7 @@ var counter = new CastCounter() {
this.lineMap = node.lineMap;
this.fileName = node.sourceFile.name;
- // Using Java.super API to call super class method here
+ // Using Java.super API to call super class method here
return Java.super(counter).visitCompilationUnit(node, p);
},
diff --git a/samples/javafoovars.js b/samples/javafoovars.js
new file mode 100644
index 00000000..037c2bf5
--- /dev/null
+++ b/samples/javafoovars.js
@@ -0,0 +1,103 @@
+#// Usage: jjs javafoovars.js -- <directory>
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example counts number
+// of variables called "foo" in the given java source files!
+if (arguments.length == 0) {
+ print("Usage: jjs javafoovars.js -- <directory>");
+ exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+var VariableTree = Java.type("com.sun.source.tree.VariableTree");
+
+// count "foo"-s in the given .java files
+function countFoo() {
+ // get the system compiler tool
+ var compiler = ToolProvider.systemJavaCompiler;
+ // get standard file manager
+ var fileMgr = compiler.getStandardFileManager(null, null, null);
+ // Using Java.to convert script array (arguments) to a Java String[]
+ var compUnits = fileMgr.getJavaFileObjects(
+ Java.to(arguments, StringArray));
+ // create a new compilation task
+ var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+ // subclass SimpleTreeVisitor - to count variables called "foo"
+ var FooCounterVisitor = Java.extend(TreeScanner);
+ var fooCount = 0;
+
+ var visitor = new FooCounterVisitor() {
+ visitVariable: function (node, p) {
+ if (node.name.toString() == "foo") {
+ fooCount++;
+ }
+ }
+ }
+
+ for each (var cu in task.parse()) {
+ cu.accept(visitor, null);
+ }
+ return fooCount;
+}
+
+// for each ".java" file in directory (recursively) count "foo".
+function main(dir) {
+ var totalCount = 0;
+ Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+ forEach(function(p) {
+ var name = p.toFile().absolutePath;
+ if (name.endsWith(".java")) {
+ var count = 0;
+ try {
+ count = countFoo(p.toFile().getAbsolutePath());
+ } catch (e) {
+ print(e);
+ }
+ if (count != 0) {
+ print(name + ": " + count);
+ }
+ totalCount += count;
+ }
+ });
+ print("Total foo count: " + totalCount);
+}
+
+main(new File(arguments[0]));
diff --git a/samples/javaimporter.js b/samples/javaimporter.js
index dd487ec1..3e3cb1ba 100644
--- a/samples/javaimporter.js
+++ b/samples/javaimporter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -34,14 +34,14 @@
function readTextFromURL(url) {
- // equivalent to
- //
+ // equivalent to
+ //
// import java.io.*;
// import java.net.*;
// import java.lang.StringBuffer;
//
// only inside the 'with' statement
- with (new JavaImporter(java.io,
+ with (new JavaImporter(java.io,
java.net,
java.lang.StringBuilder)) {
var buf = new StringBuilder();
diff --git a/samples/javalist.js b/samples/javalist.js
index 8f3749b5..5430dbde 100644
--- a/samples/javalist.js
+++ b/samples/javalist.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/javamap.js b/samples/javamap.js
index a53d0320..57da6203 100644
--- a/samples/javamap.js
+++ b/samples/javamap.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -45,7 +45,7 @@ print(map.get('js'));
print(map['js']);
print(map.js);
-// also assign new key-value pair
+// also assign new key-value pair
// as 'property-value'
map['language'] = 'java';
print(map.get("language"));
diff --git a/samples/javashell.js b/samples/javashell.js
index 65d1a8a2..4e71f753 100644
--- a/samples/javashell.js
+++ b/samples/javashell.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -130,7 +130,7 @@ function exec(args) {
// generate unique name
function uniqueName() {
var now = LocalDateTime.now().toString();
- // replace unsafe chars with '_'
+ // replace unsafe chars with '_'
return "JavaShell" + now.replace(/-|:|\./g, '_');
}
diff --git a/samples/jsadapter_dom.js b/samples/jsadapter_dom.js
index e86c6d2f..cb2f8baa 100644
--- a/samples/jsadapter_dom.js
+++ b/samples/jsadapter_dom.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -33,7 +33,7 @@
// Simple example that demonstrates reading XML Rss feed
// to generate a HTML file from script and show it by browser
-// Uses XML DOM parser and DOM element wrapped by script
+// Uses XML DOM parser and DOM element wrapped by script
// "proxy" (JSAdapter constructor)
// Java classes used
@@ -78,7 +78,7 @@ function getElemText(elem) {
var node = nodeList.item(i);
if (node.nodeType == TEXT_NODE) {
text += node.nodeValue;
- }
+ }
}
return text;
diff --git a/samples/jsobj_example.js b/samples/jsobj_example.js
new file mode 100644
index 00000000..d608876e
--- /dev/null
+++ b/samples/jsobj_example.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Flexible script object using AbstractJSObject subclass
+
+var AbstractJSObject = Java.type("jdk.nashorn.api.scripting.AbstractJSObject");
+
+// JSObject example that uses a map for properties and
+// falls back to with methods on a java object (for missing
+// properties
+
+function makeJSObj(map, fallback) {
+ return new AbstractJSObject() {
+ getMember: function(name) {
+ if (map.containsKey(name)) {
+ return map.get(name);
+ }
+
+ var val = fallback[name];
+ if (typeof val == 'function') {
+ return function() {
+ var a = arguments;
+ switch (a.length) {
+ case 0: return fallback[name]();
+ case 1: return fallback[name](a[0]);
+ case 2: return fallback[name](a[0], a[1]);
+ case 3: return fallback[name](a[0], a[1], a[2]);
+ case 4: return fallback[name](a[0], a[1], a[2], a[3]);
+ }
+ }
+ }
+ }
+ }
+}
+
+var m = new java.util.HashMap();
+m.put("foo", 42);
+m.put("bar", 'hello');
+
+var obj = makeJSObj(m, new java.io.File("."));
+
+print(obj.foo);
+print(obj.bar);
+print(obj.getAbsolutePath());
+print(obj.isDirectory());
diff --git a/samples/jsobject.js b/samples/jsobject.js
index 48434d7d..ad09b2f1 100644
--- a/samples/jsobject.js
+++ b/samples/jsobject.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/jsobject_mapreduce.js b/samples/jsobject_mapreduce.js
index ff34940b..174ad0a9 100644
--- a/samples/jsobject_mapreduce.js
+++ b/samples/jsobject_mapreduce.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,9 +31,9 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// Many Array.prototype functions such as map,
+// Many Array.prototype functions such as map,
// filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as
+// These functions accept ECMAScript array as well as
// many array-like objects including JSObjects.
// See also http://en.wikipedia.org/wiki/MapReduce
@@ -57,6 +57,6 @@ forEach.call(buf, function(x) print(x));
// print sum of squares of the random numbers
print("Square sum:",
reduce.call(
- map.call(buf, function(x) x*x),
+ map.call(buf, function(x) x*x),
function(x, y) x + y)
);
diff --git a/samples/jsonviewer.js b/samples/jsonviewer.js
index 804fef50..c650ae98 100644
--- a/samples/jsonviewer.js
+++ b/samples/jsonviewer.js
@@ -4,22 +4,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -52,8 +52,8 @@ var TreeView = Java.type("javafx.scene.control.TreeView");
// read text content of a URL
function readTextFromURL(url) {
- // equivalent to
- //
+ // equivalent to
+ //
// import java.io.*;
// import java.net.*;
// import java.lang.StringBuffer;
diff --git a/samples/letter.js b/samples/letter.js
index 304bf1fb..b5a58b89 100644
--- a/samples/letter.js
+++ b/samples/letter.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -43,7 +43,7 @@ var obj = { sender: $ARG[0], recipient: $ARG[1] };
// JavaScript style line comment is ok too.
print(<<EOF);
Dear ${obj.recipient},
-
+
I wish you all the best.
Regards,
diff --git a/samples/list_mapreduce.js b/samples/list_mapreduce.js
index 033f4d76..ac2df985 100644
--- a/samples/list_mapreduce.js
+++ b/samples/list_mapreduce.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,9 +31,9 @@
// Usage: jjs list_mapreduce.js
-// Many Array.prototype functions such as map,
+// Many Array.prototype functions such as map,
// filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as
+// These functions accept ECMAScript array as well as
// many array-like objects including java.util.ArrayLists.
// So, you can do map/filter/reduce with Java streams or
// you can also use Array.prototype functions as below.
@@ -81,6 +81,6 @@ forEach.call(list, function(x) print(x));
// print sum of squares of the random numbers
print("Square sum:",
reduce.call(
- map.call(list, function(x) x*x),
+ map.call(list, function(x) x*x),
function(x, y) x + y)
);
diff --git a/samples/locales.js b/samples/locales.js
index ae42f969..f16338d5 100644
--- a/samples/locales.js
+++ b/samples/locales.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/logisticmap.js b/samples/logisticmap.js
index 74198475..e9b0700b 100644
--- a/samples/logisticmap.js
+++ b/samples/logisticmap.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/options.js b/samples/options.js
index 3a10346c..9c26b391 100644
--- a/samples/options.js
+++ b/samples/options.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/parser.js b/samples/parser.js
index 2f172ccc..16334aea 100644
--- a/samples/parser.js
+++ b/samples/parser.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/readLine.js b/samples/readLine.js
index 9807d3b5..d41d35cf 100644
--- a/samples/readLine.js
+++ b/samples/readLine.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/sam_function.js b/samples/sam_function.js
index 84064732..70aa5ab0 100644
--- a/samples/sam_function.js
+++ b/samples/sam_function.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -46,6 +46,6 @@ timer.schedule(function() {
}, 1000);
// wait for timer thread to print by
-// reading from stdin.
+// reading from stdin.
print("press any key to exit after message from timer...");
System.in.read();
diff --git a/samples/shell.js b/samples/shell.js
index 93965387..8e3195ce 100644
--- a/samples/shell.js
+++ b/samples/shell.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/stack.js b/samples/stack.js
index 295ad20f..13b63fac 100644
--- a/samples/stack.js
+++ b/samples/stack.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -33,7 +33,7 @@
// error objects. This property's value is a string
// that shows script stack trace.
-function g() {
+function g() {
throw new Error("wrong");
}
@@ -44,9 +44,9 @@ function f() {
// Output looks something like:
//
// Error: wrong
-// at g (stack.js:37)
-// at f (stack.js:41)
-// at <program> (stack.js:52)
+// at g (stack.js:37)
+// at f (stack.js:41)
+// at <program> (stack.js:52)
try {
f();
diff --git a/samples/uniform_random.js b/samples/uniform_random.js
index a82cd0bb..da3f26af 100644
--- a/samples/uniform_random.js
+++ b/samples/uniform_random.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/uniq.js b/samples/uniq.js
index cbd2c34d..f9316eb4 100644
--- a/samples/uniq.js
+++ b/samples/uniq.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/uniqs.js b/samples/uniqs.js
index 57eb7c52..1c36c676 100644
--- a/samples/uniqs.js
+++ b/samples/uniqs.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -31,7 +31,7 @@
// Usage: jjs uniqs.js -- <file>
// omit repeated lines and print unique lines
-// But this version uses Stream API
+// But this version uses Stream API
if (arguments.length < 1) {
print("Usage: jjs uniqs.js -- <file>");
diff --git a/samples/weather.js b/samples/weather.js
index 75c6b265..3a37bc1d 100644
--- a/samples/weather.js
+++ b/samples/weather.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/word_histogram.js b/samples/word_histogram.js
index 9c739ea0..39f4f686 100644
--- a/samples/word_histogram.js
+++ b/samples/word_histogram.js
@@ -2,22 +2,22 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/samples/zipfs.js b/samples/zipfs.js
new file mode 100644
index 00000000..ecb6f61a
--- /dev/null
+++ b/samples/zipfs.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (arguments.length == 0) {
+ print("Usage: jjs zipfs.js -- <.zip/.jar file>")
+ exit(1)
+}
+
+var Files = Java.type("java.nio.file.Files")
+var FileSystems = Java.type("java.nio.file.FileSystems")
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption")
+var Paths = Java.type("java.nio.file.Paths")
+
+var zipfile = Paths.get(arguments[0])
+var fs = FileSystems.newFileSystem(zipfile, null)
+var root = fs.rootDirectories[0]
+Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach(
+ function(p) (print(p), print(Files.readAttributes(p, "zip:*")))
+)
+fs.close()
diff --git a/samples/ziplist.js b/samples/ziplist.js
new file mode 100644
index 00000000..214dd351
--- /dev/null
+++ b/samples/ziplist.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (arguments.length == 0) {
+ print("Usage: jjs ziplist -- <zip-file>");
+ exit(1);
+}
+
+// list the content details of a .zip or .jar file
+var file = arguments[0];
+
+// java classes used
+var Attributes = Java.type("java.util.jar.Attributes");
+var FileTime = Java.type("java.nio.file.attribute.FileTime");
+var JarFile = Java.type("java.util.jar.JarFile");
+var ZipEntry = Java.type("java.util.zip.ZipEntry");
+var ZipFile = Java.type("java.util.zip.ZipFile");
+
+var zf = file.endsWith(".jar")? new JarFile(file) : new ZipFile(file);
+
+var entries = zf.entries();
+// make overall output a valid JSON
+var zfObj = {
+ name: zf.name,
+ comment: zf.comment,
+ size: zf.size(),
+ entries: []
+};
+
+while (entries.hasMoreElements()) {
+ zfObj.entries.push(entries.nextElement());
+}
+
+print(JSON.stringify(zfObj, function (key, value) {
+ if (value instanceof ZipEntry) {
+ return Object.bindProperties({}, value);
+ } else if (value instanceof FileTime) {
+ return value.toString();
+ } else if (value instanceof Attributes) {
+ var attrs = {};
+ var itr = value.entrySet().iterator();
+ while (itr.hasNext()) {
+ var n = itr.next();
+ attrs[n.key] = String(n.value);
+ }
+ return attrs;
+ }
+
+ return value;
+}, ' '));
+
+zf.close();
diff --git a/src/jdk/internal/dynalink/ChainedCallSite.java b/src/jdk/internal/dynalink/ChainedCallSite.java
index c2ad4eb2..45f191a0 100644
--- a/src/jdk/internal/dynalink/ChainedCallSite.java
+++ b/src/jdk/internal/dynalink/ChainedCallSite.java
@@ -103,8 +103,27 @@ import jdk.internal.dynalink.support.Lookup;
* handle is always at the start of the chain.
*/
public class ChainedCallSite extends AbstractRelinkableCallSite {
- private static final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class,
- MethodHandle.class);
+ private static final MethodHandle PRUNE_CATCHES =
+ MethodHandles.insertArguments(
+ Lookup.findOwnSpecial(
+ MethodHandles.lookup(),
+ "prune",
+ MethodHandle.class,
+ MethodHandle.class,
+ boolean.class),
+ 2,
+ true);
+
+ private static final MethodHandle PRUNE_SWITCHPOINTS =
+ MethodHandles.insertArguments(
+ Lookup.findOwnSpecial(
+ MethodHandles.lookup(),
+ "prune",
+ MethodHandle.class,
+ MethodHandle.class,
+ boolean.class),
+ 2,
+ false);
private final AtomicReference<LinkedList<GuardedInvocation>> invocations = new AtomicReference<>();
@@ -112,7 +131,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
* Creates a new chained call site.
* @param descriptor the descriptor for the call site.
*/
- public ChainedCallSite(CallSiteDescriptor descriptor) {
+ public ChainedCallSite(final CallSiteDescriptor descriptor) {
super(descriptor);
}
@@ -126,24 +145,26 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
@Override
- public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
- relinkInternal(guardedInvocation, fallback, false);
+ public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+ relinkInternal(guardedInvocation, fallback, false, false);
}
@Override
- public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
- relinkInternal(guardedInvocation, fallback, true);
+ public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+ relinkInternal(guardedInvocation, fallback, true, false);
}
- private MethodHandle relinkInternal(GuardedInvocation invocation, MethodHandle relink, boolean reset) {
+ private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
final LinkedList<GuardedInvocation> currentInvocations = invocations.get();
@SuppressWarnings({ "unchecked", "rawtypes" })
final LinkedList<GuardedInvocation> newInvocations =
currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone();
- // First, prune the chain of invalidated switchpoints.
- for(Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
- if(it.next().hasBeenInvalidated()) {
+ // First, prune the chain of invalidated switchpoints, we always do this
+ // We also remove any catches if the remove catches flag is set
+ for(final Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
+ final GuardedInvocation inv = it.next();
+ if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) {
it.remove();
}
}
@@ -160,12 +181,13 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
// prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we
// rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger.
- final MethodHandle pruneAndInvoke = makePruneAndInvokeMethod(relink);
+ final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, getPruneSwitchpoints());
+ final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, getPruneCatches());
// Fold the new chain
MethodHandle target = relink;
- for(GuardedInvocation inv: newInvocations) {
- target = inv.compose(pruneAndInvoke, target);
+ for(final GuardedInvocation inv: newInvocations) {
+ target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches);
}
// If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case
@@ -178,14 +200,30 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
/**
+ * Get the switchpoint pruning function for a chained call site
+ * @return function that removes invalidated switchpoints tied to callsite guard chain and relinks
+ */
+ protected MethodHandle getPruneSwitchpoints() {
+ return PRUNE_SWITCHPOINTS;
+ }
+
+ /**
+ * Get the catch pruning function for a chained call site
+ * @return function that removes all catches tied to callsite guard chain and relinks
+ */
+ protected MethodHandle getPruneCatches() {
+ return PRUNE_CATCHES;
+ }
+
+ /**
* Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
* chain.
* @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
* @return a method handle for prune-and-invoke
*/
- private MethodHandle makePruneAndInvokeMethod(MethodHandle relink) {
+ private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) {
// Bind prune to (this, relink)
- final MethodHandle boundPrune = MethodHandles.insertArguments(PRUNE, 0, this, relink);
+ final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink);
// Make it ignore all incoming arguments
final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
// Invoke prune, then invoke the call site target with original arguments
@@ -193,7 +231,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
}
@SuppressWarnings("unused")
- private MethodHandle prune(MethodHandle relink) {
- return relinkInternal(null, relink, false);
+ private MethodHandle prune(final MethodHandle relink, final boolean catches) {
+ return relinkInternal(null, relink, false, catches);
}
}
diff --git a/src/jdk/internal/dynalink/DefaultBootstrapper.java b/src/jdk/internal/dynalink/DefaultBootstrapper.java
index b7edb9d8..d687fd62 100644
--- a/src/jdk/internal/dynalink/DefaultBootstrapper.java
+++ b/src/jdk/internal/dynalink/DefaultBootstrapper.java
@@ -117,7 +117,7 @@ public class DefaultBootstrapper {
* @param type the method signature at the call site
* @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
*/
- public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+ public static CallSite bootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) {
return bootstrapInternal(caller, name, type);
}
@@ -133,11 +133,11 @@ public class DefaultBootstrapper {
* @param type the method signature at the call site
* @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
*/
- public static CallSite publicBootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+ public static CallSite publicBootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) {
return bootstrapInternal(MethodHandles.publicLookup(), name, type);
}
- private static CallSite bootstrapInternal(MethodHandles.Lookup caller, String name, MethodType type) {
+ private static CallSite bootstrapInternal(final MethodHandles.Lookup caller, final String name, final MethodType type) {
return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type)));
}
}
diff --git a/src/jdk/internal/dynalink/DynamicLinker.java b/src/jdk/internal/dynalink/DynamicLinker.java
index 155ff309..e7e58d2a 100644
--- a/src/jdk/internal/dynalink/DynamicLinker.java
+++ b/src/jdk/internal/dynalink/DynamicLinker.java
@@ -140,7 +140,6 @@ import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
* @author Attila Szegedi
*/
public class DynamicLinker {
-
private static final String CLASS_NAME = DynamicLinker.class.getName();
private static final String RELINK_METHOD_NAME = "relink";
@@ -148,6 +147,7 @@ public class DynamicLinker {
private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
private final LinkerServices linkerServices;
+ private final GuardedInvocationFilter prelinkFilter;
private final int runtimeContextArgCount;
private final boolean syncOnRelink;
private final int unstableRelinkThreshold;
@@ -156,18 +156,20 @@ public class DynamicLinker {
* Creates a new dynamic linker.
*
* @param linkerServices the linkerServices used by the linker, created by the factory.
+ * @param prelinkFilter see {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter)}
* @param runtimeContextArgCount see {@link DynamicLinkerFactory#setRuntimeContextArgCount(int)}
*/
- DynamicLinker(LinkerServices linkerServices, int runtimeContextArgCount, boolean syncOnRelink,
- int unstableRelinkThreshold) {
+ DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationFilter prelinkFilter, final int runtimeContextArgCount,
+ final boolean syncOnRelink, final int unstableRelinkThreshold) {
if(runtimeContextArgCount < 0) {
throw new IllegalArgumentException("runtimeContextArgCount < 0");
}
if(unstableRelinkThreshold < 0) {
throw new IllegalArgumentException("unstableRelinkThreshold < 0");
}
- this.runtimeContextArgCount = runtimeContextArgCount;
this.linkerServices = linkerServices;
+ this.prelinkFilter = prelinkFilter;
+ this.runtimeContextArgCount = runtimeContextArgCount;
this.syncOnRelink = syncOnRelink;
this.unstableRelinkThreshold = unstableRelinkThreshold;
}
@@ -199,7 +201,7 @@ public class DynamicLinker {
private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME,
MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class);
- private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, int relinkCount) {
+ private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) {
// Make a bound MH of invoke() for this linker and call site
final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf(
relinkCount));
@@ -219,16 +221,15 @@ public class DynamicLinker {
* @throws Exception rethrows any exception thrown by the linkers
*/
@SuppressWarnings("unused")
- private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
+ private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
final LinkRequest linkRequest =
- runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments)
- : new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments,
- runtimeContextArgCount);
+ runtimeContextArgCount == 0 ?
+ new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
+ new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
- // Find a suitable method handle with a guard
GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
// None found - throw an exception
@@ -248,6 +249,11 @@ public class DynamicLinker {
}
}
+ // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
+ // return type of the invocation to the call site.
+ guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
+ guardedInvocation.getClass(); // null pointer check
+
int newRelinkCount = relinkCount;
// Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
// threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
diff --git a/src/jdk/internal/dynalink/DynamicLinkerFactory.java b/src/jdk/internal/dynalink/DynamicLinkerFactory.java
index 72fbebe3..2f4e5f33 100644
--- a/src/jdk/internal/dynalink/DynamicLinkerFactory.java
+++ b/src/jdk/internal/dynalink/DynamicLinkerFactory.java
@@ -97,24 +97,26 @@ import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
import jdk.internal.dynalink.support.AutoDiscovery;
import jdk.internal.dynalink.support.BottomGuardingDynamicLinker;
import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider;
import jdk.internal.dynalink.support.CompositeGuardingDynamicLinker;
import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.DefaultPrelinkFilter;
import jdk.internal.dynalink.support.LinkerServicesImpl;
import jdk.internal.dynalink.support.TypeConverterFactory;
+import jdk.internal.dynalink.support.TypeUtilities;
/**
* A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
* of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
- * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker}. See
- * {@link DynamicLinker} documentation for tips on how to use this class.
+ * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker} and a
+ * {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on how to use this class.
*
* @author Attila Szegedi
*/
public class DynamicLinkerFactory {
-
/**
* Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}.
*/
@@ -128,6 +130,8 @@ public class DynamicLinkerFactory {
private int runtimeContextArgCount = 0;
private boolean syncOnRelink = false;
private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
+ private GuardedInvocationFilter prelinkFilter;
+ private MethodTypeConversionStrategy autoConversionStrategy;
/**
* Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread
@@ -135,7 +139,7 @@ public class DynamicLinkerFactory {
*
* @param classLoader the class loader used for the autodiscovery of available linkers.
*/
- public void setClassLoader(ClassLoader classLoader) {
+ public void setClassLoader(final ClassLoader classLoader) {
this.classLoader = classLoader;
classLoaderExplicitlySet = true;
}
@@ -149,7 +153,7 @@ public class DynamicLinkerFactory {
* @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers
* (this is also the default value).
*/
- public void setPrioritizedLinkers(List<? extends GuardingDynamicLinker> prioritizedLinkers) {
+ public void setPrioritizedLinkers(final List<? extends GuardingDynamicLinker> prioritizedLinkers) {
this.prioritizedLinkers =
prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers);
}
@@ -162,7 +166,7 @@ public class DynamicLinkerFactory {
*
* @param prioritizedLinkers a list of prioritized linkers.
*/
- public void setPrioritizedLinkers(GuardingDynamicLinker... prioritizedLinkers) {
+ public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) {
setPrioritizedLinkers(Arrays.asList(prioritizedLinkers));
}
@@ -173,7 +177,7 @@ public class DynamicLinkerFactory {
* @param prioritizedLinker the single prioritized linker. Must not be null.
* @throws IllegalArgumentException if null is passed.
*/
- public void setPrioritizedLinker(GuardingDynamicLinker prioritizedLinker) {
+ public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) {
if(prioritizedLinker == null) {
throw new IllegalArgumentException("prioritizedLinker == null");
}
@@ -188,7 +192,7 @@ public class DynamicLinkerFactory {
* @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
* fallback linkers.
*/
- public void setFallbackLinkers(List<? extends GuardingDynamicLinker> fallbackLinkers) {
+ public void setFallbackLinkers(final List<? extends GuardingDynamicLinker> fallbackLinkers) {
this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers);
}
@@ -200,7 +204,7 @@ public class DynamicLinkerFactory {
* @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
* fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used.
*/
- public void setFallbackLinkers(GuardingDynamicLinker... fallbackLinkers) {
+ public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) {
setFallbackLinkers(Arrays.asList(fallbackLinkers));
}
@@ -214,7 +218,7 @@ public class DynamicLinkerFactory {
*
* @param runtimeContextArgCount the number of language runtime context arguments in call sites.
*/
- public void setRuntimeContextArgCount(int runtimeContextArgCount) {
+ public void setRuntimeContextArgCount(final int runtimeContextArgCount) {
if(runtimeContextArgCount < 0) {
throw new IllegalArgumentException("runtimeContextArgCount < 0");
}
@@ -227,7 +231,7 @@ public class DynamicLinkerFactory {
* multithreaded execution of dynamically linked code.
* @param syncOnRelink true for invoking sync on relink, false otherwise.
*/
- public void setSyncOnRelink(boolean syncOnRelink) {
+ public void setSyncOnRelink(final boolean syncOnRelink) {
this.syncOnRelink = syncOnRelink;
}
@@ -238,7 +242,7 @@ public class DynamicLinkerFactory {
* call sites will never be considered unstable.
* @see LinkRequest#isCallSiteUnstable()
*/
- public void setUnstableRelinkThreshold(int unstableRelinkThreshold) {
+ public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) {
if(unstableRelinkThreshold < 0) {
throw new IllegalArgumentException("unstableRelinkThreshold < 0");
}
@@ -246,7 +250,42 @@ public class DynamicLinkerFactory {
}
/**
- * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers.
+ * Set the pre-link filter. This is a {@link GuardedInvocationFilter} that will get the final chance to modify the
+ * guarded invocation after it has been created by a component linker and before the dynamic linker links it into
+ * the call site. It is normally used to adapt the return value type of the invocation to the type of the call site.
+ * When not set explicitly, {@link DefaultPrelinkFilter} will be used.
+ * @param prelinkFilter the pre-link filter for the dynamic linker.
+ */
+ public void setPrelinkFilter(final GuardedInvocationFilter prelinkFilter) {
+ this.prelinkFilter = prelinkFilter;
+ }
+
+ /**
+ * Sets an object representing the conversion strategy for automatic type conversions. After
+ * {@link TypeConverterFactory#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has
+ * applied all custom conversions to a method handle, it still needs to effect
+ * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that
+ * can usually be automatically applied as per
+ * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}.
+ * However, sometimes language runtimes will want to customize even those conversions for their own call
+ * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by
+ * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom
+ * automatic conversion strategy, that can deal with null values. Note that when the strategy's
+ * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)}
+ * is invoked, the custom language conversions will already have been applied to the method handle, so by
+ * design the difference between the handle's current method type and the desired final type will always
+ * only be ones that can be subjected to method invocation conversions. The strategy also doesn't need to
+ * invoke a final {@code MethodHandle.asType()} as the converter factory will do that as the final step.
+ * @param autoConversionStrategy the strategy for applying method invocation conversions for the linker
+ * created by this factory.
+ */
+ public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) {
+ this.autoConversionStrategy = autoConversionStrategy;
+ }
+
+ /**
+ * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as
+ * the pre-link filter.
*
* @return the new dynamic Linker
*/
@@ -275,7 +314,7 @@ public class DynamicLinkerFactory {
// ... prioritized linkers, ...
linkers.addAll(prioritizedLinkers);
// ... filtered discovered linkers, ...
- for(GuardingDynamicLinker linker: discovered) {
+ for(final GuardingDynamicLinker linker: discovered) {
if(!knownLinkerClasses.contains(linker.getClass())) {
linkers.add(linker);
}
@@ -300,14 +339,19 @@ public class DynamicLinkerFactory {
}
final List<GuardingTypeConverterFactory> typeConverters = new LinkedList<>();
- for(GuardingDynamicLinker linker: linkers) {
+ for(final GuardingDynamicLinker linker: linkers) {
if(linker instanceof GuardingTypeConverterFactory) {
typeConverters.add((GuardingTypeConverterFactory)linker);
}
}
- return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite),
- runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold);
+ if(prelinkFilter == null) {
+ prelinkFilter = new DefaultPrelinkFilter();
+ }
+
+ return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters,
+ autoConversionStrategy), composite), prelinkFilter, runtimeContextArgCount, syncOnRelink,
+ unstableRelinkThreshold);
}
private static ClassLoader getThreadContextClassLoader() {
@@ -319,9 +363,9 @@ public class DynamicLinkerFactory {
}, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT);
}
- private static void addClasses(Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
- List<? extends GuardingDynamicLinker> linkers) {
- for(GuardingDynamicLinker linker: linkers) {
+ private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
+ final List<? extends GuardingDynamicLinker> linkers) {
+ for(final GuardingDynamicLinker linker: linkers) {
knownLinkerClasses.add(linker.getClass());
}
}
diff --git a/src/jdk/internal/dynalink/GuardedInvocationFilter.java b/src/jdk/internal/dynalink/GuardedInvocationFilter.java
new file mode 100644
index 00000000..8560d82f
--- /dev/null
+++ b/src/jdk/internal/dynalink/GuardedInvocationFilter.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+ Copyright 2009-2013 Attila Szegedi
+
+ Licensed under both the Apache License, Version 2.0 (the "Apache License")
+ and the BSD License (the "BSD License"), with licensee being free to
+ choose either of the two at their discretion.
+
+ You may not use this file except in compliance with either the Apache
+ License or the BSD License.
+
+ If you choose to use this file in compliance with the Apache License, the
+ following notice applies to you:
+
+ You may obtain a copy of the Apache License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ If you choose to use this file in compliance with the BSD License, the
+ following notice applies to you:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.internal.dynalink;
+
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+
+/**
+ * Interface for objects that are used to transform one guarded invocation into another one. Typical usage is for
+ * implementing {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter) pre-link filters}.
+ */
+public interface GuardedInvocationFilter {
+ /**
+ * Given a guarded invocation, return a potentially different guarded invocation.
+ * @param inv the original guarded invocation. Null is never passed.
+ * @param linkRequest the link request for which the invocation was generated (usually by some linker).
+ * @param linkerServices the linker services that can be used during creation of a new invocation.
+ * @return either the passed guarded invocation or a different one, with the difference usually determined based on
+ * information in the link request and the differing invocation created with the assistance of the linker services.
+ * Whether or not {@code null} is an accepted return value is dependent on the user of the filter.
+ */
+ public GuardedInvocation filter(GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices);
+}
diff --git a/src/jdk/internal/dynalink/MonomorphicCallSite.java b/src/jdk/internal/dynalink/MonomorphicCallSite.java
index 7f1bbede..98541f28 100644
--- a/src/jdk/internal/dynalink/MonomorphicCallSite.java
+++ b/src/jdk/internal/dynalink/MonomorphicCallSite.java
@@ -99,17 +99,17 @@ public class MonomorphicCallSite extends AbstractRelinkableCallSite {
* Creates a new call site with monomorphic inline caching strategy.
* @param descriptor the descriptor for this call site
*/
- public MonomorphicCallSite(CallSiteDescriptor descriptor) {
+ public MonomorphicCallSite(final CallSiteDescriptor descriptor) {
super(descriptor);
}
@Override
- public void relink(GuardedInvocation guardedInvocation, MethodHandle relink) {
+ public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
setTarget(guardedInvocation.compose(relink));
}
@Override
- public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relink) {
+ public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
relink(guardedInvocation, relink);
}
}
diff --git a/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java b/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
index 8a73af92..879a4b0e 100644
--- a/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
+++ b/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
@@ -97,7 +97,7 @@ public class NoSuchDynamicMethodException extends RuntimeException {
* Creates a new NoSuchDynamicMethodException
* @param message the message of the exception.
*/
- public NoSuchDynamicMethodException(String message) {
+ public NoSuchDynamicMethodException(final String message) {
super(message);
}
}
diff --git a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
index a6ef8c11..b8e8a3df 100644
--- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
+++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
@@ -97,7 +97,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -107,6 +106,7 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
import jdk.internal.dynalink.support.Lookup;
+import jdk.internal.dynalink.support.TypeUtilities;
/**
* A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
@@ -123,18 +123,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
private final Map<String, DynamicMethod> methods = new HashMap<>();
- AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) {
+ AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard) {
this(clazz, classGuard, classGuard);
}
- AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard, MethodHandle assignableGuard) {
+ AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) {
this.clazz = clazz;
this.classGuard = classGuard;
this.assignableGuard = assignableGuard;
final FacetIntrospector introspector = createFacetIntrospector();
// Add methods and properties
- for(Method method: introspector.getMethods()) {
+ for(final Method method: introspector.getMethods()) {
final String name = method.getName();
// Add method
addMember(name, method, methods);
@@ -153,7 +153,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
// Add field getter/setters as property getters/setters.
- for(Field field: introspector.getFields()) {
+ for(final Field field: introspector.getFields()) {
final String name = field.getName();
// Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
if(!propertyGetters.containsKey(name)) {
@@ -166,7 +166,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
// Add inner classes, but only those for which we don't hide a property with it
- for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
+ for(final Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
final String name = innerClassSpec.getKey();
if(!propertyGetters.containsKey(name)) {
setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
@@ -174,7 +174,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
}
- private static String decapitalize(String str) {
+ private static String decapitalize(final String str) {
assert str != null;
if(str.isEmpty()) {
return str;
@@ -209,7 +209,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
return getUnmodifiableKeys(methods);
}
- private static Collection<String> getUnmodifiableKeys(Map<String, ?> m) {
+ private static Collection<String> getUnmodifiableKeys(final Map<String, ?> m) {
return Collections.unmodifiableCollection(m.keySet());
}
@@ -222,7 +222,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param handle the method handle that implements the property getter
* @param validationType the validation type for the property
*/
- private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) {
+ private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) {
propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
}
@@ -232,7 +232,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
* names starting with "is".
*/
- private void setPropertyGetter(Method getter, int prefixLen) {
+ private void setPropertyGetter(final Method getter, final int prefixLen) {
setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
}
@@ -246,15 +246,15 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param handle the method handle that implements the property getter
* @param validationType the validation type for the property
*/
- void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
+ void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) {
setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
}
- private void addMember(String name, AccessibleObject ao, Map<String, DynamicMethod> methodMap) {
+ private void addMember(final String name, final AccessibleObject ao, final Map<String, DynamicMethod> methodMap) {
addMember(name, createDynamicMethod(ao), methodMap);
}
- private void addMember(String name, SingleDynamicMethod method, Map<String, DynamicMethod> methodMap) {
+ private void addMember(final String name, final SingleDynamicMethod method, final Map<String, DynamicMethod> methodMap) {
final DynamicMethod existingMethod = methodMap.get(name);
final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
if(newMethod != existingMethod) {
@@ -270,9 +270,9 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param name the common name of the reflective members.
* @return a dynamic method representing all the specified reflective members.
*/
- static DynamicMethod createDynamicMethod(Iterable<? extends AccessibleObject> members, Class<?> clazz, String name) {
+ static DynamicMethod createDynamicMethod(final Iterable<? extends AccessibleObject> members, final Class<?> clazz, final String name) {
DynamicMethod dynMethod = null;
- for(AccessibleObject method: members) {
+ for(final AccessibleObject method: members) {
dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
}
return dynMethod;
@@ -285,12 +285,23 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param m the reflective member
* @return the single dynamic method representing the reflective member
*/
- private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) {
+ private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) {
if(CallerSensitiveDetector.isCallerSensitive(m)) {
+ // Method has @CallerSensitive annotation
+ return new CallerSensitiveDynamicMethod(m);
+ }
+ // Method has no @CallerSensitive annotation
+ final MethodHandle mh;
+ try {
+ mh = unreflectSafely(m);
+ } catch (final IllegalAccessError e) {
+ // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't
+ // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive.
return new CallerSensitiveDynamicMethod(m);
}
+ // Proceed with non-caller sensitive
final Member member = (Member)m;
- return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName());
+ return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor);
}
/**
@@ -301,7 +312,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param m the method or constructor
* @return the method handle
*/
- private static MethodHandle unreflectSafely(AccessibleObject m) {
+ private static MethodHandle unreflectSafely(final AccessibleObject m) {
if(m instanceof Method) {
final Method reflMethod = (Method)m;
final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod);
@@ -313,7 +324,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor<?>)m));
}
- private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class<?> clazz, String name) {
+ private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class<?> clazz, final String name) {
if(existing == null) {
return method;
} else if(existing.contains(method)) {
@@ -331,7 +342,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
+ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
throws Exception {
final LinkRequest ncrequest = request.withoutRuntimeContext();
// BeansLinker already checked that the name is at least 2 elements long and the first element is "dyn".
@@ -353,8 +364,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
return null;
}
- protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> operations) throws Exception {
+ protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> operations) throws Exception {
if(operations.isEmpty()) {
return null;
}
@@ -374,27 +385,31 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
return null;
}
- static final <T> List<T> pop(List<T> l) {
+ static final <T> List<T> pop(final List<T> l) {
return l.subList(1, l.size());
}
- MethodHandle getClassGuard(CallSiteDescriptor desc) {
+ MethodHandle getClassGuard(final CallSiteDescriptor desc) {
return getClassGuard(desc.getMethodType());
}
- MethodHandle getClassGuard(MethodType type) {
+ MethodHandle getClassGuard(final MethodType type) {
return Guards.asType(classGuard, type);
}
- GuardedInvocationComponent getClassGuardedInvocationComponent(MethodHandle invocation, MethodType type) {
+ GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) {
return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
- private MethodHandle getAssignableGuard(MethodType type) {
+ SingleDynamicMethod getConstructorMethod(final String signature) {
+ return null;
+ }
+
+ private MethodHandle getAssignableGuard(final MethodType type) {
return Guards.asType(assignableGuard, type);
}
- private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+ private GuardedInvocation getCallPropWithThis(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
switch(callSiteDescriptor.getNameTokenCount()) {
case 3: {
return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
@@ -406,25 +421,25 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
}
- private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){
+ private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap){
final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
}
- private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap) {
+ private MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap) {
final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
}
- private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) {
+ private DynamicMethod getDynamicMethod(final String methodName, final Map<String, DynamicMethod> methodMap) {
final DynamicMethod dynaMethod = methodMap.get(methodName);
return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
}
- private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName,
- Map<String, DynamicMethod> methodsMap) {
+ private SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName,
+ final Map<String, DynamicMethod> methodsMap) {
// What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
// to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
// resolution works correctly in almost every situation. However, in presence of many language-specific
@@ -433,23 +448,33 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
// for performance reasons.
// Is the method name lexically of the form "name(types)"?
- final int lastChar = methodName.length() - 1;
- if(methodName.charAt(lastChar) != ')') {
+ final int lastChar = fullName.length() - 1;
+ if(fullName.charAt(lastChar) != ')') {
return null;
}
- final int openBrace = methodName.indexOf('(');
+ final int openBrace = fullName.indexOf('(');
if(openBrace == -1) {
return null;
}
+ final String name = fullName.substring(0, openBrace);
+ final String signature = fullName.substring(openBrace + 1, lastChar);
+
// Find an existing method for the "name" part
- final DynamicMethod simpleNamedMethod = methodsMap.get(methodName.substring(0, openBrace));
+ final DynamicMethod simpleNamedMethod = methodsMap.get(name);
if(simpleNamedMethod == null) {
+ // explicit signature constructor access
+ // Java.type("java.awt.Color")["(int,int,int)"]
+ // will get Color(int,int,int) constructor of Color class.
+ if (name.isEmpty()) {
+ return getConstructorMethod(signature);
+ }
+
return null;
}
// Try to get a narrowed dynamic method for the explicit parameter types.
- return simpleNamedMethod.getMethodForExactParamTypes(methodName.substring(openBrace + 1, lastChar));
+ return simpleNamedMethod.getMethodForExactParamTypes(signature);
}
private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
@@ -457,14 +482,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
- private GuardedInvocationComponent getPropertySetter(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> operations) throws Exception {
- final MethodType type = callSiteDescriptor.getMethodType();
+ private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> operations) throws Exception {
switch(callSiteDescriptor.getNameTokenCount()) {
case 2: {
// Must have three arguments: target object, property name, and property value.
assertParameterCount(callSiteDescriptor, 3);
+ // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
+ // valid for us to convert return values proactively. Also, since we don't know what setters will be
+ // invoked, we'll conservatively presume Object return type.
+ final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
+
// What's below is basically:
// foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
// get_setter_handle(type, linkerServices))
@@ -473,8 +502,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
// component's invocation.
// Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
- // abbreviate to R(O, N, V) going forward.
- // We want setters that conform to "R(O, V)"
+ // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
+ // Object return type).
final MethodType setterType = type.dropParameterTypes(1, 2);
// Bind property setter handle to the expected setter type and linker services. Type is
// MethodHandle(Object, String, Object)
@@ -495,11 +524,11 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
final MethodHandle fallbackFolded;
if(nextComponent == null) {
- // Object(MethodHandle)->R(MethodHandle, O, N, V); returns constant null
+ // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
} else {
- // R(O, N, V)->R(MethodHandle, O, N, V); adapts the next component's invocation to drop the
+ // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
// extra argument resulting from fold
fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
0, MethodHandle.class);
@@ -543,11 +572,14 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
"getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class));
private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
- private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> ops) throws Exception {
- final MethodType type = callSiteDescriptor.getMethodType();
+ private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> ops) throws Exception {
switch(callSiteDescriptor.getNameTokenCount()) {
case 2: {
+ // Since we can't know what kind of a getter we'll get back on different invocations, we'll just
+ // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking
+ // runtime might not allow coercing at that call site.
+ final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
// Must have exactly two arguments: receiver and name
assertParameterCount(callSiteDescriptor, 2);
@@ -563,11 +595,11 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup());
final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
callSiteBoundMethodGetter);
- // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0)
+ // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
// Since it's in the target of a fold, drop the unnecessary second argument
- // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1)
+ // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1)
final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
type.parameterType(1));
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
@@ -575,17 +607,19 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
final MethodHandle fallbackFolded;
if(nextComponent == null) {
- // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null
+ // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null
fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
} else {
- // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the
- // extra argument resulting from fold
- fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
- 0, AnnotatedDynamicMethod.class);
+ // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to
+ // drop the extra argument resulting from fold and to change its return type to Object.
+ final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation();
+ final MethodType nextType = nextInvocation.type();
+ fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType(
+ nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class);
}
- // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
+ // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
if(nextComponent == null) {
@@ -612,8 +646,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
// value is null.
final ValidationType validationType = annGetter.validationType;
// TODO: we aren't using the type that declares the most generic getter here!
- return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType,
- type), clazz, validationType);
+ return new GuardedInvocationComponent(getter, getGuard(validationType,
+ callSiteDescriptor.getMethodType()), clazz, validationType);
}
default: {
// Can't do anything with more than 3 name components
@@ -622,7 +656,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
}
- private MethodHandle getGuard(ValidationType validationType, MethodType methodType) {
+ private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) {
switch(validationType) {
case EXACT_CLASS: {
return getClassGuard(methodType);
@@ -642,21 +676,25 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
}
- private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
- MethodType.methodType(boolean.class, DynamicMethod.class));
- private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class);
+ private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class,
+ MethodType.methodType(boolean.class, Object.class));
+ private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class);
- private GuardedInvocationComponent getMethodGetter(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> ops) throws Exception {
- final MethodType type = callSiteDescriptor.getMethodType();
+ private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> ops) throws Exception {
+ // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to
+ // be visible outside of this linker, declare it to return Object.
+ final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
switch(callSiteDescriptor.getNameTokenCount()) {
case 2: {
// Must have exactly two arguments: receiver and name
assertParameterCount(callSiteDescriptor, 2);
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
linkerServices, ops);
- if(nextComponent == null) {
- // No next component operation; just return a component for this operation.
+ if(nextComponent == null || !TypeUtilities.areAssignable(DynamicMethod.class,
+ nextComponent.getGuardedInvocation().getInvocation().type().returnType())) {
+ // No next component operation, or it can never produce a dynamic method; just return a component
+ // for this operation.
return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
}
@@ -665,21 +703,20 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
// bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
// DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
- final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
- DynamicMethod.class));
+ final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type);
// Since it is part of the foldArgument() target, it will have extra args that we need to drop.
final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
- DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
- DynamicMethod.class));
+ OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class));
final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
- // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
- assert nextComponentInvocation.type().equals(type);
+ // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the
+ // return type.
+ assert nextComponentInvocation.type().changeReturnType(type.returnType()).equals(type);
// Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
- DynamicMethod.class);
+ Object.class);
// Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
- IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
+ IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter);
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
@@ -695,7 +732,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
// No delegation to the next component of the composite operation; if we have a method with that name,
// we'll always return it at this point.
return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
- MethodHandles.constant(DynamicMethod.class, method), 0, type.parameterType(0)), type), type);
+ MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
}
default: {
// Can't do anything with more than 3 name components
@@ -704,7 +741,31 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
}
}
- private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
+ static class MethodPair {
+ final MethodHandle method1;
+ final MethodHandle method2;
+
+ MethodPair(final MethodHandle method1, final MethodHandle method2) {
+ this.method1 = method1;
+ this.method2 = method2;
+ }
+
+ MethodHandle guardWithTest(final MethodHandle test) {
+ return MethodHandles.guardWithTest(test, method1, method2);
+ }
+ }
+
+ static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) {
+ final MethodType type1 = m1.type();
+ final MethodType type2 = m2.type();
+ final Class<?> commonRetType = TypeUtilities.getCommonLosslessConversionType(type1.returnType(),
+ type2.returnType());
+ return new MethodPair(
+ m1.asType(type1.changeReturnType(commonRetType)),
+ m2.asType(type2.changeReturnType(commonRetType)));
+ }
+
+ private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
if(descriptor.getMethodType().parameterCount() != paramCount) {
throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
}
@@ -719,7 +780,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @return the method handle for retrieving the property, or null if the property does not exist
*/
@SuppressWarnings("unused")
- private Object getPropertyGetterHandle(Object id) {
+ private Object getPropertyGetterHandle(final Object id) {
return propertyGetters.get(id);
}
@@ -733,17 +794,20 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
@SuppressWarnings("unused")
- private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices,
- Object id) {
+ private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices,
+ final Object id) {
return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
}
private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
- "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class);
+ "getDynamicMethod", Object.class, Object.class), 1, Object.class);
private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
@SuppressWarnings("unused")
- private DynamicMethod getDynamicMethod(Object name) {
+ // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't
+ // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for
+ // "dyn:getMethod" linking).
+ private Object getDynamicMethod(final Object name) {
return getDynamicMethod(String.valueOf(name), methods);
}
@@ -754,7 +818,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
* method with the specified name does not exist.
*/
- DynamicMethod getDynamicMethod(String name) {
+ DynamicMethod getDynamicMethod(final String name) {
return getDynamicMethod(name, methods);
}
@@ -765,16 +829,16 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @param getter the getter
* @return getter with same name, declared on the most generic superclass/interface of the declaring class
*/
- private static Method getMostGenericGetter(Method getter) {
+ private static Method getMostGenericGetter(final Method getter) {
return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
}
- private static Method getMostGenericGetter(String name, Class<?> returnType, Class<?> declaringClass) {
+ private static Method getMostGenericGetter(final String name, final Class<?> returnType, final Class<?> declaringClass) {
if(declaringClass == null) {
return null;
}
// Prefer interfaces
- for(Class<?> itf: declaringClass.getInterfaces()) {
+ for(final Class<?> itf: declaringClass.getInterfaces()) {
final Method itfGetter = getMostGenericGetter(name, returnType, itf);
if(itfGetter != null) {
return itfGetter;
@@ -787,7 +851,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
try {
return declaringClass.getMethod(name);
- } catch(NoSuchMethodException e) {
+ } catch(final NoSuchMethodException e) {
// Intentionally ignored, meant to fall through
}
}
@@ -798,18 +862,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
private final SingleDynamicMethod method;
/*private*/ final ValidationType validationType;
- AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) {
+ AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) {
this.method = method;
this.validationType = validationType;
}
- MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+ MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
return method.getInvocation(callSiteDescriptor, linkerServices);
}
@SuppressWarnings("unused")
- MethodHandle getTarget(MethodHandles.Lookup lookup) {
- MethodHandle inv = method.getTarget(lookup);
+ MethodHandle getTarget(final MethodHandles.Lookup lookup) {
+ final MethodHandle inv = method.getTarget(lookup);
assert inv != null;
return inv;
}
diff --git a/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java b/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
index 72beadfe..21789e45 100644
--- a/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
+++ b/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
@@ -104,7 +104,7 @@ import java.util.Set;
class AccessibleMembersLookup {
private final Map<MethodSignature, Method> methods;
private final Set<Class<?>> innerClasses;
- private boolean instance;
+ private final boolean instance;
/**
* Creates a mapping for all accessible methods and inner classes on a class.
@@ -112,7 +112,7 @@ class AccessibleMembersLookup {
* @param clazz the inspected class
* @param instance true to inspect instance methods, false to inspect static methods.
*/
- AccessibleMembersLookup(final Class<?> clazz, boolean instance) {
+ AccessibleMembersLookup(final Class<?> clazz, final boolean instance) {
this.methods = new HashMap<>();
this.innerClasses = new LinkedHashSet<>();
this.instance = instance;
@@ -153,7 +153,7 @@ class AccessibleMembersLookup {
* @param name the name of the method this signature represents.
* @param args the argument types of the method.
*/
- MethodSignature(String name, Class<?>[] args) {
+ MethodSignature(final String name, final Class<?>[] args) {
this.name = name;
this.args = args;
}
@@ -210,7 +210,7 @@ class AccessibleMembersLookup {
if(!CheckRestrictedPackage.isRestrictedClass(clazz)) {
searchSuperTypes = false;
- for(Method method: clazz.getMethods()) {
+ for(final Method method: clazz.getMethods()) {
final boolean isStatic = Modifier.isStatic(method.getModifiers());
if(instance != isStatic) {
final MethodSignature sig = new MethodSignature(method);
@@ -237,7 +237,7 @@ class AccessibleMembersLookup {
}
}
}
- for(Class<?> innerClass: clazz.getClasses()) {
+ for(final Class<?> innerClass: clazz.getClasses()) {
// Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just
// expose non-static classes with explicit constructor outer class argument.
// NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes
diff --git a/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java b/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
index 39a03a8e..e749c490 100644
--- a/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
+++ b/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
@@ -108,7 +108,7 @@ class ApplicableOverloadedMethods {
ApplicableOverloadedMethods(final List<SingleDynamicMethod> methods, final MethodType callSiteType,
final ApplicabilityTest test) {
this.methods = new LinkedList<>();
- for(SingleDynamicMethod m: methods) {
+ for(final SingleDynamicMethod m: methods) {
if(test.isApplicable(callSiteType, m)) {
this.methods.add(m);
}
@@ -143,7 +143,7 @@ class ApplicableOverloadedMethods {
*/
static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() {
@Override
- boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+ boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
final MethodType methodType = method.getMethodType();
final int methodArity = methodType.parameterCount();
if(methodArity != callSiteType.parameterCount()) {
@@ -165,7 +165,7 @@ class ApplicableOverloadedMethods {
*/
static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() {
@Override
- boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+ boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
final MethodType methodType = method.getMethodType();
final int methodArity = methodType.parameterCount();
if(methodArity != callSiteType.parameterCount()) {
@@ -188,7 +188,7 @@ class ApplicableOverloadedMethods {
*/
static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() {
@Override
- boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+ boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
if(!method.isVarArgs()) {
return false;
}
diff --git a/src/jdk/internal/dynalink/beans/BeanIntrospector.java b/src/jdk/internal/dynalink/beans/BeanIntrospector.java
index fc54e353..754d88ef 100644
--- a/src/jdk/internal/dynalink/beans/BeanIntrospector.java
+++ b/src/jdk/internal/dynalink/beans/BeanIntrospector.java
@@ -88,7 +88,7 @@ import java.util.Collections;
import java.util.Map;
class BeanIntrospector extends FacetIntrospector {
- BeanIntrospector(Class<?> clazz) {
+ BeanIntrospector(final Class<?> clazz) {
super(clazz, true);
}
@@ -98,7 +98,7 @@ class BeanIntrospector extends FacetIntrospector {
}
@Override
- MethodHandle editMethodHandle(MethodHandle mh) {
+ MethodHandle editMethodHandle(final MethodHandle mh) {
return mh;
}
}
diff --git a/src/jdk/internal/dynalink/beans/BeanLinker.java b/src/jdk/internal/dynalink/beans/BeanLinker.java
index d0ad96ba..f7f0c94a 100644
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java
+++ b/src/jdk/internal/dynalink/beans/BeanLinker.java
@@ -106,7 +106,7 @@ import jdk.internal.dynalink.support.TypeUtilities;
* @author Attila Szegedi
*/
class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker {
- BeanLinker(Class<?> clazz) {
+ BeanLinker(final Class<?> clazz) {
super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz));
if(clazz.isArray()) {
// Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an
@@ -119,7 +119,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
}
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return type == clazz;
}
@@ -129,8 +129,8 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
}
@Override
- protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> operations) throws Exception {
+ protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> operations) throws Exception {
final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor,
linkerServices, operations);
if(superGic != null) {
@@ -166,7 +166,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
- final LinkerServices linkerServices, List<String> operations) throws Exception {
+ final LinkerServices linkerServices, final List<String> operations) throws Exception {
final MethodType callSiteType = callSiteDescriptor.getMethodType();
final Class<?> declaredType = callSiteType.parameterType(0);
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
@@ -237,8 +237,9 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
} else {
checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
}
- return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
- binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
+ final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+ nextComponent.getGuardedInvocation().getInvocation());
+ return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
@@ -247,7 +248,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
CallSiteDescriptor.NAME_OPERAND);
}
- private static Object convertKeyToInteger(String fixedKey, LinkerServices linkerServices) throws Exception {
+ private static Object convertKeyToInteger(final String fixedKey, final LinkerServices linkerServices) throws Exception {
try {
if(linkerServices.canConvert(String.class, Number.class)) {
try {
@@ -267,18 +268,18 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
return Integer.valueOf(intIndex);
} catch(Exception|Error e) {
throw e;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
return Integer.valueOf(fixedKey);
- } catch(NumberFormatException e) {
+ } catch(final NumberFormatException e) {
// key is not a number
return null;
}
}
- private static MethodHandle convertArgToInt(MethodHandle mh, LinkerServices ls, CallSiteDescriptor desc) {
+ private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) {
final Class<?> sourceType = desc.getMethodType().parameterType(1);
if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) {
return mh;
@@ -301,21 +302,21 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
private final MethodType methodType;
private final Object fixedKey;
- Binder(LinkerServices linkerServices, MethodType methodType, Object fixedKey) {
+ Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) {
this.linkerServices = linkerServices;
this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass());
this.fixedKey = fixedKey;
}
- /*private*/ MethodHandle bind(MethodHandle handle) {
- return bindToFixedKey(linkerServices.asType(handle, methodType));
+ /*private*/ MethodHandle bind(final MethodHandle handle) {
+ return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType));
}
- /*private*/ MethodHandle bindTest(MethodHandle handle) {
+ /*private*/ MethodHandle bindTest(final MethodHandle handle) {
return bindToFixedKey(Guards.asType(handle, methodType));
}
- private MethodHandle bindToFixedKey(MethodHandle handle) {
+ private MethodHandle bindToFixedKey(final MethodHandle handle) {
return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey);
}
}
@@ -325,12 +326,12 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
MethodType.methodType(boolean.class, Object.class));
- private static MethodHandle findRangeCheck(Class<?> collectionType) {
+ private static MethodHandle findRangeCheck(final Class<?> collectionType) {
return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class);
}
@SuppressWarnings("unused")
- private static final boolean rangeCheck(Object array, Object index) {
+ private static final boolean rangeCheck(final Object array, final Object index) {
if(!(index instanceof Number)) {
return false;
}
@@ -347,7 +348,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
}
@SuppressWarnings("unused")
- private static final boolean rangeCheck(List<?> list, Object index) {
+ private static final boolean rangeCheck(final List<?> list, final Object index) {
if(!(index instanceof Number)) {
return false;
}
@@ -369,8 +370,8 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
MethodType.methodType(Object.class, Object.class, Object.class));
- private GuardedInvocationComponent getElementSetter(CallSiteDescriptor callSiteDescriptor,
- LinkerServices linkerServices, List<String> operations) throws Exception {
+ private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor,
+ final LinkerServices linkerServices, final List<String> operations) throws Exception {
final MethodType callSiteType = callSiteDescriptor.getMethodType();
final Class<?> declaredType = callSiteType.parameterType(0);
@@ -440,8 +441,9 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
- return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
- binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
+ final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+ nextComponent.getGuardedInvocation().getInvocation());
+ return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
@@ -456,7 +458,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
- private GuardedInvocationComponent getLengthGetter(CallSiteDescriptor callSiteDescriptor) {
+ private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) {
assertParameterCount(callSiteDescriptor, 1);
final MethodType callSiteType = callSiteDescriptor.getMethodType();
final Class<?> declaredType = callSiteType.parameterType(0);
@@ -486,7 +488,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
return null;
}
- private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
+ private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
if(descriptor.getMethodType().parameterCount() != paramCount) {
throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
}
diff --git a/src/jdk/internal/dynalink/beans/BeansLinker.java b/src/jdk/internal/dynalink/beans/BeansLinker.java
index e0c14b0d..439c5a65 100644
--- a/src/jdk/internal/dynalink/beans/BeansLinker.java
+++ b/src/jdk/internal/dynalink/beans/BeansLinker.java
@@ -131,7 +131,7 @@ import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
public class BeansLinker implements GuardingDynamicLinker {
private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
@Override
- protected TypeBasedGuardingDynamicLinker computeValue(Class<?> clazz) {
+ protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) {
// If ClassValue.put() were public, we could just pre-populate with these known mappings...
return
clazz == Class.class ? new ClassLinker() :
@@ -154,7 +154,7 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a bean linker for that class
*/
- public static TypeBasedGuardingDynamicLinker getLinkerForClass(Class<?> clazz) {
+ public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) {
return linkers.get(clazz);
}
@@ -169,12 +169,32 @@ public class BeansLinker implements GuardingDynamicLinker {
}
/**
+ * Returns true if the object is a Dynalink Java constructor.
+ *
+ * @param obj the object we want to test for being a constructor
+ * @return true if it is a constructor, false otherwise.
+ */
+ public static boolean isDynamicConstructor(final Object obj) {
+ return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor();
+ }
+
+ /**
+ * Return the dynamic method of constructor of the given class and the given signature.
+ * @param clazz the class
+ * @param signature full signature of the constructor
+ * @return DynamicMethod for the constructor
+ */
+ public static Object getConstructorMethod(final Class<?> clazz, final String signature) {
+ return StaticClassLinker.getConstructorMethod(clazz, signature);
+ }
+
+ /**
* Returns a collection of names of all readable instance properties of a class.
* @param clazz the class
* @return a collection of names of all readable instance properties of a class.
*/
- public static Collection<String> getReadableInstancePropertyNames(Class<?> clazz) {
- TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+ public static Collection<String> getReadableInstancePropertyNames(final Class<?> clazz) {
+ final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
if(linker instanceof BeanLinker) {
return ((BeanLinker)linker).getReadablePropertyNames();
}
@@ -186,8 +206,8 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a collection of names of all writable instance properties of a class.
*/
- public static Collection<String> getWritableInstancePropertyNames(Class<?> clazz) {
- TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+ public static Collection<String> getWritableInstancePropertyNames(final Class<?> clazz) {
+ final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
if(linker instanceof BeanLinker) {
return ((BeanLinker)linker).getWritablePropertyNames();
}
@@ -199,8 +219,8 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a collection of names of all instance methods of a class.
*/
- public static Collection<String> getInstanceMethodNames(Class<?> clazz) {
- TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+ public static Collection<String> getInstanceMethodNames(final Class<?> clazz) {
+ final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
if(linker instanceof BeanLinker) {
return ((BeanLinker)linker).getMethodNames();
}
@@ -212,7 +232,7 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a collection of names of all readable static properties of a class.
*/
- public static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) {
+ public static Collection<String> getReadableStaticPropertyNames(final Class<?> clazz) {
return StaticClassLinker.getReadableStaticPropertyNames(clazz);
}
@@ -221,7 +241,7 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a collection of names of all writable static properties of a class.
*/
- public static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) {
+ public static Collection<String> getWritableStaticPropertyNames(final Class<?> clazz) {
return StaticClassLinker.getWritableStaticPropertyNames(clazz);
}
@@ -230,12 +250,12 @@ public class BeansLinker implements GuardingDynamicLinker {
* @param clazz the class
* @return a collection of names of all static methods of a class.
*/
- public static Collection<String> getStaticMethodNames(Class<?> clazz) {
+ public static Collection<String> getStaticMethodNames(final Class<?> clazz) {
return StaticClassLinker.getStaticMethodNames(clazz);
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
+ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
throws Exception {
final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
final int l = callSiteDescriptor.getNameTokenCount();
diff --git a/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java b/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
index 466bafe6..e4ada355 100644
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
@@ -107,14 +107,14 @@ public class CallerSensitiveDetector {
private static final DetectionStrategy DETECTION_STRATEGY = getDetectionStrategy();
- static boolean isCallerSensitive(AccessibleObject ao) {
+ static boolean isCallerSensitive(final AccessibleObject ao) {
return DETECTION_STRATEGY.isCallerSensitive(ao);
}
private static DetectionStrategy getDetectionStrategy() {
try {
return new PrivilegedDetectionStrategy();
- } catch(Throwable t) {
+ } catch(final Throwable t) {
return new UnprivilegedDetectionStrategy();
}
}
@@ -127,7 +127,7 @@ public class CallerSensitiveDetector {
private static final Class<? extends Annotation> CALLER_SENSITIVE_ANNOTATION_CLASS = CallerSensitive.class;
@Override
- boolean isCallerSensitive(AccessibleObject ao) {
+ boolean isCallerSensitive(final AccessibleObject ao) {
return ao.getAnnotation(CALLER_SENSITIVE_ANNOTATION_CLASS) != null;
}
}
@@ -136,8 +136,8 @@ public class CallerSensitiveDetector {
private static final String CALLER_SENSITIVE_ANNOTATION_STRING = "@sun.reflect.CallerSensitive()";
@Override
- boolean isCallerSensitive(AccessibleObject o) {
- for(Annotation a: o.getAnnotations()) {
+ boolean isCallerSensitive(final AccessibleObject o) {
+ for(final Annotation a: o.getAnnotations()) {
if(String.valueOf(a).equals(CALLER_SENSITIVE_ANNOTATION_STRING)) {
return true;
}
diff --git a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
index 1e274d51..2896732e 100644
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
@@ -107,13 +107,13 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
private final AccessibleObject target;
private final MethodType type;
- public CallerSensitiveDynamicMethod(AccessibleObject target) {
+ public CallerSensitiveDynamicMethod(final AccessibleObject target) {
super(getName(target));
this.target = target;
this.type = getMethodType(target);
}
- private static String getName(AccessibleObject target) {
+ private static String getName(final AccessibleObject target) {
final Member m = (Member)target;
return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
m.getName()));
@@ -124,7 +124,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
return type;
}
- private static MethodType getMethodType(AccessibleObject ao) {
+ private static MethodType getMethodType(final AccessibleObject ao) {
final boolean isMethod = ao instanceof Method;
final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass();
final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes();
@@ -144,7 +144,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
}
@Override
- MethodHandle getTarget(MethodHandles.Lookup lookup) {
+ MethodHandle getTarget(final MethodHandles.Lookup lookup) {
if(target instanceof Method) {
final MethodHandle mh = Lookup.unreflect(lookup, (Method)target);
if(Modifier.isStatic(((Member)target).getModifiers())) {
@@ -155,4 +155,9 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup,
(Constructor<?>)target));
}
+
+ @Override
+ boolean isConstructor() {
+ return target instanceof Constructor;
+ }
}
diff --git a/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java b/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
index 360759f8..49723a12 100644
--- a/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
+++ b/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
@@ -101,7 +101,7 @@ class CheckRestrictedPackage {
* @param clazz the class to test
* @return true if the class is either not public, or it resides in a package with restricted access.
*/
- static boolean isRestrictedClass(Class<?> clazz) {
+ static boolean isRestrictedClass(final Class<?> clazz) {
if(!Modifier.isPublic(clazz.getModifiers())) {
// Non-public classes are always restricted
return true;
@@ -126,7 +126,7 @@ class CheckRestrictedPackage {
return null;
}
}, NO_PERMISSIONS_CONTEXT);
- } catch(SecurityException e) {
+ } catch(final SecurityException e) {
return true;
}
return false;
diff --git a/src/jdk/internal/dynalink/beans/ClassString.java b/src/jdk/internal/dynalink/beans/ClassString.java
index 2afbdb4f..00729cd7 100644
--- a/src/jdk/internal/dynalink/beans/ClassString.java
+++ b/src/jdk/internal/dynalink/beans/ClassString.java
@@ -104,16 +104,16 @@ final class ClassString {
private final Class<?>[] classes;
private int hashCode;
- ClassString(Class<?>[] classes) {
+ ClassString(final Class<?>[] classes) {
this.classes = classes;
}
- ClassString(MethodType type) {
+ ClassString(final MethodType type) {
this(type.parameterArray());
}
@Override
- public boolean equals(Object other) {
+ public boolean equals(final Object other) {
if(!(other instanceof ClassString)) {
return false;
}
@@ -150,7 +150,7 @@ final class ClassString {
return true;
}
- List<MethodHandle> getMaximallySpecifics(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
+ List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg),
varArg, classes, linkerServices);
}
@@ -158,7 +158,7 @@ final class ClassString {
/**
* Returns all methods that are applicable to actual parameter classes represented by this ClassString object.
*/
- LinkedList<MethodHandle> getApplicables(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
+ LinkedList<MethodHandle> getApplicables(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
final LinkedList<MethodHandle> list = new LinkedList<>();
for(final MethodHandle member: methods) {
if(isApplicable(member, linkerServices, varArg)) {
@@ -173,7 +173,7 @@ final class ClassString {
* object.
*
*/
- private boolean isApplicable(MethodHandle method, LinkerServices linkerServices, boolean varArg) {
+ private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) {
final Class<?>[] formalTypes = method.type().parameterArray();
final int cl = classes.length;
final int fl = formalTypes.length - (varArg ? 1 : 0);
@@ -203,7 +203,7 @@ final class ClassString {
return true;
}
- private static boolean canConvert(LinkerServices ls, Class<?> from, Class<?> to) {
+ private static boolean canConvert(final LinkerServices ls, final Class<?> from, final Class<?> to) {
if(from == NULL_CLASS) {
return !to.isPrimitive();
}
diff --git a/src/jdk/internal/dynalink/beans/DynamicMethod.java b/src/jdk/internal/dynalink/beans/DynamicMethod.java
index 6beb92b1..7b7a4d80 100644
--- a/src/jdk/internal/dynalink/beans/DynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/DynamicMethod.java
@@ -99,7 +99,7 @@ import jdk.internal.dynalink.linker.LinkerServices;
abstract class DynamicMethod {
private final String name;
- DynamicMethod(String name) {
+ DynamicMethod(final String name) {
this.name = name;
}
@@ -138,7 +138,7 @@ abstract class DynamicMethod {
*/
abstract boolean contains(SingleDynamicMethod method);
- static String getClassAndMethodName(Class<?> clazz, String name) {
+ static String getClassAndMethodName(final Class<?> clazz, final String name) {
final String clazzName = clazz.getCanonicalName();
return (clazzName == null ? clazz.getName() : clazzName) + "." + name;
}
@@ -147,4 +147,13 @@ abstract class DynamicMethod {
public String toString() {
return "[" + getClass().getName() + " " + getName() + "]";
}
+
+ /**
+ * True if this method happens to be a constructor method.
+ *
+ * @return true if this represents a constructor.
+ */
+ boolean isConstructor() {
+ return false;
+ }
}
diff --git a/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java b/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
index 32942b9a..7067c2ce 100644
--- a/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
+++ b/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
@@ -99,12 +99,12 @@ import jdk.internal.dynalink.support.Guards;
*/
class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return DynamicMethod.class.isAssignableFrom(type);
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) {
final Object receiver = linkRequest.getReceiver();
if(!(receiver instanceof DynamicMethod)) {
return null;
@@ -114,15 +114,30 @@ class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
return null;
}
final String operator = desc.getNameToken(CallSiteDescriptor.OPERATOR);
- if(operator == "call") {
- final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation(
+ final DynamicMethod dynMethod = (DynamicMethod)receiver;
+ final boolean constructor = dynMethod.isConstructor();
+ final MethodHandle invocation;
+
+ if (operator == "call" && !constructor) {
+ invocation = dynMethod.getInvocation(
CallSiteDescriptorFactory.dropParameterTypes(desc, 0, 1), linkerServices);
- if(invocation == null) {
+ } else if (operator == "new" && constructor) {
+ final MethodHandle ctorInvocation = dynMethod.getInvocation(desc, linkerServices);
+ if(ctorInvocation == null) {
return null;
}
+
+ // Insert null for StaticClass parameter
+ invocation = MethodHandles.insertArguments(ctorInvocation, 0, (Object)null);
+ } else {
+ return null;
+ }
+
+ if (invocation != null) {
return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0,
- desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
+ desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
}
+
return null;
}
}
diff --git a/src/jdk/internal/dynalink/beans/FacetIntrospector.java b/src/jdk/internal/dynalink/beans/FacetIntrospector.java
index 4ac5deaa..29c98d04 100644
--- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java
+++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java
@@ -106,7 +106,7 @@ abstract class FacetIntrospector {
protected final AccessibleMembersLookup membersLookup;
- FacetIntrospector(Class<?> clazz, boolean instance) {
+ FacetIntrospector(final Class<?> clazz, final boolean instance) {
this.clazz = clazz;
this.instance = instance;
isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz);
@@ -135,7 +135,7 @@ abstract class FacetIntrospector {
final Field[] fields = clazz.getFields();
final Collection<Field> cfields = new ArrayList<>(fields.length);
- for(Field field: fields) {
+ for(final Field field: fields) {
final boolean isStatic = Modifier.isStatic(field.getModifiers());
if(isStatic && clazz != field.getDeclaringClass()) {
// ignore inherited static fields
@@ -149,7 +149,7 @@ abstract class FacetIntrospector {
return cfields;
}
- boolean isAccessible(Member m) {
+ boolean isAccessible(final Member m) {
final Class<?> declaring = m.getDeclaringClass();
// (declaring == clazz) is just an optimization - we're calling this only from code that operates on a
// non-restriced class, so if the declaring class is identical to the class being inspected, then forego
@@ -166,11 +166,11 @@ abstract class FacetIntrospector {
}
- MethodHandle unreflectGetter(Field field) {
+ MethodHandle unreflectGetter(final Field field) {
return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field));
}
- MethodHandle unreflectSetter(Field field) {
+ MethodHandle unreflectSetter(final Field field) {
return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field));
}
diff --git a/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java b/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
index f2c76dba..9bacd218 100644
--- a/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
+++ b/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
@@ -105,38 +105,38 @@ class GuardedInvocationComponent {
private final GuardedInvocation guardedInvocation;
private final Validator validator;
- GuardedInvocationComponent(MethodHandle invocation) {
+ GuardedInvocationComponent(final MethodHandle invocation) {
this(invocation, null, ValidationType.NONE);
}
- GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, ValidationType validationType) {
+ GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) {
this(invocation, guard, null, validationType);
}
- GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Class<?> validatorClass,
- ValidationType validationType) {
+ GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
+ final ValidationType validationType) {
this(invocation, guard, new Validator(validatorClass, validationType));
}
- GuardedInvocationComponent(GuardedInvocation guardedInvocation, Class<?> validatorClass,
- ValidationType validationType) {
+ GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class<?> validatorClass,
+ final ValidationType validationType) {
this(guardedInvocation, new Validator(validatorClass, validationType));
}
- GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation) {
+ GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) {
return replaceInvocation(newInvocation, guardedInvocation.getGuard());
}
- GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation, MethodHandle newGuard) {
+ GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) {
return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation,
newGuard), validator);
}
- private GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Validator validator) {
+ private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) {
this(new GuardedInvocation(invocation, guard), validator);
}
- private GuardedInvocationComponent(GuardedInvocation guardedInvocation, Validator validator) {
+ private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) {
this.guardedInvocation = guardedInvocation;
this.validator = validator;
}
@@ -153,8 +153,8 @@ class GuardedInvocationComponent {
return validator.validationType;
}
- GuardedInvocationComponent compose(MethodHandle compositeInvocation, MethodHandle otherGuard,
- Class<?> otherValidatorClass, ValidationType otherValidationType) {
+ GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard,
+ final Class<?> otherValidatorClass, final ValidationType otherValidationType) {
final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType));
final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard;
return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator);
@@ -164,12 +164,12 @@ class GuardedInvocationComponent {
/*private*/ final Class<?> validatorClass;
/*private*/ final ValidationType validationType;
- Validator(Class<?> validatorClass, ValidationType validationType) {
+ Validator(final Class<?> validatorClass, final ValidationType validationType) {
this.validatorClass = validatorClass;
this.validationType = validationType;
}
- Validator compose(Validator other) {
+ Validator compose(final Validator other) {
if(other.validationType == ValidationType.NONE) {
return this;
}
@@ -240,7 +240,7 @@ class GuardedInvocationComponent {
throw new AssertionError("Incompatible composition " + this + " vs " + other);
}
- private boolean isAssignableFrom(Validator other) {
+ private boolean isAssignableFrom(final Validator other) {
return validatorClass.isAssignableFrom(other.validatorClass);
}
diff --git a/src/jdk/internal/dynalink/beans/MaximallySpecific.java b/src/jdk/internal/dynalink/beans/MaximallySpecific.java
index 3ee8e41a..8b5e3214 100644
--- a/src/jdk/internal/dynalink/beans/MaximallySpecific.java
+++ b/src/jdk/internal/dynalink/beans/MaximallySpecific.java
@@ -105,7 +105,7 @@ class MaximallySpecific {
* @param varArgs whether to assume the methods are varargs
* @return the list of maximally specific methods.
*/
- static List<SingleDynamicMethod> getMaximallySpecificMethods(List<SingleDynamicMethod> methods, boolean varArgs) {
+ static List<SingleDynamicMethod> getMaximallySpecificMethods(final List<SingleDynamicMethod> methods, final boolean varArgs) {
return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null);
}
@@ -116,7 +116,7 @@ class MaximallySpecific {
private static final MethodTypeGetter<MethodHandle> METHOD_HANDLE_TYPE_GETTER =
new MethodTypeGetter<MethodHandle>() {
@Override
- MethodType getMethodType(MethodHandle t) {
+ MethodType getMethodType(final MethodHandle t) {
return t.type();
}
};
@@ -124,7 +124,7 @@ class MaximallySpecific {
private static final MethodTypeGetter<SingleDynamicMethod> DYNAMIC_METHOD_TYPE_GETTER =
new MethodTypeGetter<SingleDynamicMethod>() {
@Override
- MethodType getMethodType(SingleDynamicMethod t) {
+ MethodType getMethodType(final SingleDynamicMethod t) {
return t.getMethodType();
}
};
@@ -138,8 +138,8 @@ class MaximallySpecific {
* @param argTypes concrete argument types for the invocation
* @return the list of maximally specific method handles.
*/
- static List<MethodHandle> getMaximallySpecificMethodHandles(List<MethodHandle> methods, boolean varArgs,
- Class<?>[] argTypes, LinkerServices ls) {
+ static List<MethodHandle> getMaximallySpecificMethodHandles(final List<MethodHandle> methods, final boolean varArgs,
+ final Class<?>[] argTypes, final LinkerServices ls) {
return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER);
}
@@ -152,8 +152,8 @@ class MaximallySpecific {
* @param argTypes concrete argument types for the invocation
* @return the list of maximally specific methods.
*/
- static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(List<SingleDynamicMethod> methods,
- boolean varArgs, Class<?>[] argTypes, LinkerServices ls) {
+ static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(final List<SingleDynamicMethod> methods,
+ final boolean varArgs, final Class<?>[] argTypes, final LinkerServices ls) {
return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER);
}
@@ -166,16 +166,16 @@ class MaximallySpecific {
* @param argTypes concrete argument types for the invocation
* @return the list of maximally specific methods.
*/
- private static <T> List<T> getMaximallySpecificMethods(List<T> methods, boolean varArgs,
- Class<?>[] argTypes, LinkerServices ls, MethodTypeGetter<T> methodTypeGetter) {
+ private static <T> List<T> getMaximallySpecificMethods(final List<T> methods, final boolean varArgs,
+ final Class<?>[] argTypes, final LinkerServices ls, final MethodTypeGetter<T> methodTypeGetter) {
if(methods.size() < 2) {
return methods;
}
final LinkedList<T> maximals = new LinkedList<>();
- for(T m: methods) {
+ for(final T m: methods) {
final MethodType methodType = methodTypeGetter.getMethodType(m);
boolean lessSpecific = false;
- for(Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) {
+ for(final Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) {
final T max = maximal.next();
switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) {
case TYPE_1_BETTER: {
@@ -202,8 +202,8 @@ class MaximallySpecific {
return maximals;
}
- private static Comparison isMoreSpecific(MethodType t1, MethodType t2, boolean varArgs, Class<?>[] argTypes,
- LinkerServices ls) {
+ private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class<?>[] argTypes,
+ final LinkerServices ls) {
final int pc1 = t1.parameterCount();
final int pc2 = t2.parameterCount();
assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1);
@@ -241,7 +241,7 @@ class MaximallySpecific {
return Comparison.INDETERMINATE;
}
- private static Comparison compare(Class<?> c1, Class<?> c2, Class<?>[] argTypes, int i, LinkerServices cmp) {
+ private static Comparison compare(final Class<?> c1, final Class<?> c2, final Class<?>[] argTypes, final int i, final LinkerServices cmp) {
if(cmp != null) {
final Comparison c = cmp.compareConversion(argTypes[i], c1, c2);
if(c != Comparison.INDETERMINATE) {
@@ -256,7 +256,7 @@ class MaximallySpecific {
return Comparison.INDETERMINATE;
}
- private static Class<?> getParameterClass(MethodType t, int l, int i, boolean varArgs) {
+ private static Class<?> getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) {
return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i);
}
}
diff --git a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
index 8ce41bc6..83156e3b 100644
--- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
@@ -115,20 +115,20 @@ class OverloadedDynamicMethod extends DynamicMethod {
* @param clazz the class this method belongs to
* @param name the name of the method
*/
- OverloadedDynamicMethod(Class<?> clazz, String name) {
+ OverloadedDynamicMethod(final Class<?> clazz, final String name) {
this(new LinkedList<SingleDynamicMethod>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name));
}
- private OverloadedDynamicMethod(LinkedList<SingleDynamicMethod> methods, ClassLoader classLoader, String name) {
+ private OverloadedDynamicMethod(final LinkedList<SingleDynamicMethod> methods, final ClassLoader classLoader, final String name) {
super(name);
this.methods = methods;
this.classLoader = classLoader;
}
@Override
- SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
+ SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) {
final LinkedList<SingleDynamicMethod> matchingMethods = new LinkedList<>();
- for(SingleDynamicMethod method: methods) {
+ for(final SingleDynamicMethod method: methods) {
final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes);
if(matchingMethod != null) {
matchingMethods.add(matchingMethod);
@@ -148,7 +148,6 @@ class OverloadedDynamicMethod extends DynamicMethod {
}
}
- @SuppressWarnings("fallthrough")
@Override
public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
final MethodType callSiteType = callSiteDescriptor.getMethodType();
@@ -207,7 +206,7 @@ class OverloadedDynamicMethod extends DynamicMethod {
case 1: {
// Very lucky, we ended up with a single candidate method handle based on the call site signature; we
// can link it very simply by delegating to the SingleDynamicMethod.
- invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices);
+ return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices);
}
default: {
// We have more than one candidate. We have no choice but to link to a method that resolves overloads on
@@ -218,7 +217,7 @@ class OverloadedDynamicMethod extends DynamicMethod {
// has an already determined Lookup.
final List<MethodHandle> methodHandles = new ArrayList<>(invokables.size());
final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup();
- for(SingleDynamicMethod method: invokables) {
+ for(final SingleDynamicMethod method: invokables) {
methodHandles.add(method.getTarget(lookup));
}
return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker();
@@ -228,8 +227,8 @@ class OverloadedDynamicMethod extends DynamicMethod {
}
@Override
- public boolean contains(SingleDynamicMethod m) {
- for(SingleDynamicMethod method: methods) {
+ public boolean contains(final SingleDynamicMethod m) {
+ for(final SingleDynamicMethod method: methods) {
if(method.contains(m)) {
return true;
}
@@ -237,12 +236,18 @@ class OverloadedDynamicMethod extends DynamicMethod {
return false;
}
+ @Override
+ public boolean isConstructor() {
+ assert !methods.isEmpty();
+ return methods.getFirst().isConstructor();
+ }
+
ClassLoader getClassLoader() {
return classLoader;
}
- private static boolean isApplicableDynamically(LinkerServices linkerServices, MethodType callSiteType,
- SingleDynamicMethod m) {
+ private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType,
+ final SingleDynamicMethod m) {
final MethodType methodType = m.getMethodType();
final boolean varArgs = m.isVarArgs();
final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
@@ -288,13 +293,13 @@ class OverloadedDynamicMethod extends DynamicMethod {
return true;
}
- private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType,
- Class<?> methodType) {
+ private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class<?> callSiteType,
+ final Class<?> methodType) {
return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType)
|| linkerServices.canConvert(callSiteType, methodType);
}
- private ApplicableOverloadedMethods getApplicables(MethodType callSiteType, ApplicabilityTest test) {
+ private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) {
return new ApplicableOverloadedMethods(methods, callSiteType, test);
}
@@ -303,7 +308,12 @@ class OverloadedDynamicMethod extends DynamicMethod {
*
* @param method a method to add
*/
- public void addMethod(SingleDynamicMethod method) {
+ public void addMethod(final SingleDynamicMethod method) {
+ assert constructorFlagConsistent(method);
methods.add(method);
}
+
+ private boolean constructorFlagConsistent(final SingleDynamicMethod method) {
+ return methods.isEmpty()? true : (methods.getFirst().isConstructor() == method.isConstructor());
+ }
}
diff --git a/src/jdk/internal/dynalink/beans/OverloadedMethod.java b/src/jdk/internal/dynalink/beans/OverloadedMethod.java
index f711489b..70ec495a 100644
--- a/src/jdk/internal/dynalink/beans/OverloadedMethod.java
+++ b/src/jdk/internal/dynalink/beans/OverloadedMethod.java
@@ -93,6 +93,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Lookup;
+import jdk.internal.dynalink.support.TypeUtilities;
/**
* Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or
@@ -111,16 +112,18 @@ class OverloadedMethod {
private final ArrayList<MethodHandle> fixArgMethods;
private final ArrayList<MethodHandle> varArgMethods;
- OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
- LinkerServices linkerServices) {
+ OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
+ final LinkerServices linkerServices) {
this.parent = parent;
- this.callSiteType = callSiteType;
+ final Class<?> commonRetType = getCommonReturnType(methodHandles);
+ this.callSiteType = callSiteType.changeReturnType(commonRetType);
this.linkerServices = linkerServices;
fixArgMethods = new ArrayList<>(methodHandles.size());
varArgMethods = new ArrayList<>(methodHandles.size());
final int argNum = callSiteType.parameterCount();
for(MethodHandle mh: methodHandles) {
+ mh = mh.asType(mh.type().changeReturnType(commonRetType));
if(mh.isVarargsCollector()) {
final MethodHandle asFixed = mh.asFixedArity();
if(argNum == asFixed.type().parameterCount()) {
@@ -137,7 +140,7 @@ class OverloadedMethod {
final MethodHandle bound = SELECT_METHOD.bindTo(this);
final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
callSiteType.changeReturnType(MethodHandle.class));
- invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
+ invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(this.callSiteType), collecting);
}
MethodHandle getInvoker() {
@@ -148,8 +151,8 @@ class OverloadedMethod {
MethodHandle.class, Object[].class);
@SuppressWarnings("unused")
- private MethodHandle selectMethod(Object[] args) throws NoSuchMethodException {
- final Class<?>[] argTypes = new Class[args.length];
+ private MethodHandle selectMethod(final Object[] args) throws NoSuchMethodException {
+ final Class<?>[] argTypes = new Class<?>[args.length];
for(int i = 0; i < argTypes.length; ++i) {
final Object arg = args[i];
argTypes[i] = arg == null ? ClassString.NULL_CLASS : arg.getClass();
@@ -185,7 +188,7 @@ class OverloadedMethod {
return method;
}
- private MethodHandle getNoSuchMethodThrower(Class<?>[] argTypes) {
+ private MethodHandle getNoSuchMethodThrower(final Class<?>[] argTypes) {
return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes));
}
@@ -193,7 +196,7 @@ class OverloadedMethod {
"throwNoSuchMethod", void.class, Class[].class);
@SuppressWarnings("unused")
- private void throwNoSuchMethod(Class<?>[] argTypes) throws NoSuchMethodException {
+ private void throwNoSuchMethod(final Class<?>[] argTypes) throws NoSuchMethodException {
if(varArgMethods.isEmpty()) {
throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) +
" of method " + parent.getName() + " match the argument types " + argTypesString(argTypes));
@@ -203,11 +206,11 @@ class OverloadedMethod {
parent.getName() + " match the argument types " + argTypesString(argTypes));
}
- private MethodHandle getAmbiguousMethodThrower(Class<?>[] argTypes, List<MethodHandle> methods) {
+ private MethodHandle getAmbiguousMethodThrower(final Class<?>[] argTypes, final List<MethodHandle> methods) {
return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods));
}
- private MethodHandle adaptThrower(MethodHandle rawThrower) {
+ private MethodHandle adaptThrower(final MethodHandle rawThrower) {
return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType);
}
@@ -215,20 +218,20 @@ class OverloadedMethod {
"throwAmbiguousMethod", void.class, Class[].class, List.class);
@SuppressWarnings("unused")
- private void throwAmbiguousMethod(Class<?>[] argTypes, List<MethodHandle> methods) throws NoSuchMethodException {
+ private void throwAmbiguousMethod(final Class<?>[] argTypes, final List<MethodHandle> methods) throws NoSuchMethodException {
final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed";
throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " +
getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " +
argTypesString(argTypes));
}
- private static String argTypesString(Class<?>[] classes) {
+ private static String argTypesString(final Class<?>[] classes) {
final StringBuilder b = new StringBuilder().append('[');
appendTypes(b, classes, false);
return b.append(']').toString();
}
- private static String getSignatureList(List<MethodHandle> methods) {
+ private static String getSignatureList(final List<MethodHandle> methods) {
final StringBuilder b = new StringBuilder().append('[');
final Iterator<MethodHandle> it = methods.iterator();
if(it.hasNext()) {
@@ -240,13 +243,13 @@ class OverloadedMethod {
return b.append(']').toString();
}
- private static void appendSig(StringBuilder b, MethodHandle m) {
+ private static void appendSig(final StringBuilder b, final MethodHandle m) {
b.append('(');
appendTypes(b, m.type().parameterArray(), m.isVarargsCollector());
b.append(')');
}
- private static void appendTypes(StringBuilder b, Class<?>[] classes, boolean varArg) {
+ private static void appendTypes(final StringBuilder b, final Class<?>[] classes, final boolean varArg) {
final int l = classes.length;
if(!varArg) {
if(l > 1) {
@@ -262,4 +265,13 @@ class OverloadedMethod {
b.append(classes[l - 1].getComponentType().getCanonicalName()).append("...");
}
}
+
+ private static Class<?> getCommonReturnType(final List<MethodHandle> methodHandles) {
+ final Iterator<MethodHandle> it = methodHandles.iterator();
+ Class<?> retType = it.next().type().returnType();
+ while(it.hasNext()) {
+ retType = TypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType());
+ }
+ return retType;
+ }
}
diff --git a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
index 9d4d6961..f4a8b0a0 100644
--- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
@@ -98,6 +98,7 @@ import java.lang.invoke.MethodType;
*/
class SimpleDynamicMethod extends SingleDynamicMethod {
private final MethodHandle target;
+ private final boolean constructor;
/**
* Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle
@@ -107,12 +108,26 @@ class SimpleDynamicMethod extends SingleDynamicMethod {
* @param clazz the class declaring the method
* @param name the simple name of the method
*/
- SimpleDynamicMethod(MethodHandle target, Class<?> clazz, String name) {
+ SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name) {
+ this(target, clazz, name, false);
+ }
+
+ /**
+ * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle
+ * signature.
+ *
+ * @param target the target method handle
+ * @param clazz the class declaring the method
+ * @param name the simple name of the method
+ * @param constructor does this represent a constructor?
+ */
+ SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
super(getName(target, clazz, name));
this.target = target;
+ this.constructor = constructor;
}
- private static String getName(MethodHandle target, Class<?> clazz, String name) {
+ private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
}
@@ -127,7 +142,12 @@ class SimpleDynamicMethod extends SingleDynamicMethod {
}
@Override
- MethodHandle getTarget(Lookup lookup) {
+ MethodHandle getTarget(final Lookup lookup) {
return target;
}
+
+ @Override
+ boolean isConstructor() {
+ return constructor;
+ }
}
diff --git a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
index 6b55d81f..79dca9a3 100644
--- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
@@ -104,7 +104,7 @@ abstract class SingleDynamicMethod extends DynamicMethod {
private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class);
- SingleDynamicMethod(String name) {
+ SingleDynamicMethod(final String name) {
super(name);
}
@@ -128,22 +128,22 @@ abstract class SingleDynamicMethod extends DynamicMethod {
abstract MethodHandle getTarget(MethodHandles.Lookup lookup);
@Override
- MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+ MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(),
linkerServices);
}
@Override
- SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
+ SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) {
return typeMatchesDescription(paramTypes, getMethodType()) ? this : null;
}
@Override
- boolean contains(SingleDynamicMethod method) {
+ boolean contains(final SingleDynamicMethod method) {
return getMethodType().parameterList().equals(method.getMethodType().parameterList());
}
- static String getMethodNameWithSignature(MethodType type, String methodName) {
+ static String getMethodNameWithSignature(final MethodType type, final String methodName) {
final String typeStr = type.toString();
final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
int secondParamIndex = typeStr.indexOf(',') + 1;
@@ -156,13 +156,15 @@ abstract class SingleDynamicMethod extends DynamicMethod {
/**
* Given a method handle and a call site type, adapts the method handle to the call site type. Performs type
* conversions as needed using the specified linker services, and in case that the method handle is a vararg
- * collector, matches it to the arity of the call site.
+ * collector, matches it to the arity of the call site. The type of the return value is only changed if it can be
+ * converted using a conversion that loses neither precision nor magnitude, see
+ * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}.
* @param target the method handle to adapt
* @param callSiteType the type of the call site
* @param linkerServices the linker services used for type conversions
* @return the adapted method handle.
*/
- static MethodHandle getInvocation(MethodHandle target, MethodType callSiteType, LinkerServices linkerServices) {
+ static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) {
final MethodType methodType = target.type();
final int paramsLen = methodType.parameterCount();
final boolean varArgs = target.isVarargsCollector();
@@ -264,7 +266,7 @@ abstract class SingleDynamicMethod extends DynamicMethod {
}
@SuppressWarnings("unused")
- private static boolean canConvertTo(final LinkerServices linkerServices, Class<?> to, Object obj) {
+ private static boolean canConvertTo(final LinkerServices linkerServices, final Class<?> to, final Object obj) {
return obj == null ? false : linkerServices.canConvert(obj.getClass(), to);
}
@@ -277,7 +279,7 @@ abstract class SingleDynamicMethod extends DynamicMethod {
* @param parameterCount the total number of arguments in the new method handle
* @return a collecting method handle
*/
- static MethodHandle collectArguments(MethodHandle target, final int parameterCount) {
+ static MethodHandle collectArguments(final MethodHandle target, final int parameterCount) {
final MethodType methodType = target.type();
final int fixParamsLen = methodType.parameterCount() - 1;
final Class<?> arrayType = methodType.parameterType(fixParamsLen);
@@ -286,10 +288,10 @@ abstract class SingleDynamicMethod extends DynamicMethod {
private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod,
final LinkerServices linkerServices, final MethodType callSiteType) {
- return linkerServices.asType(sizedMethod, callSiteType);
+ return linkerServices.asTypeLosslessReturn(sizedMethod, callSiteType);
}
- private static boolean typeMatchesDescription(String paramTypes, MethodType type) {
+ private static boolean typeMatchesDescription(final String paramTypes, final MethodType type) {
final StringTokenizer tok = new StringTokenizer(paramTypes, ", ");
for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver
if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) {
@@ -299,7 +301,7 @@ abstract class SingleDynamicMethod extends DynamicMethod {
return !tok.hasMoreTokens();
}
- private static boolean typeNameMatches(String typeName, Class<?> type) {
+ private static boolean typeNameMatches(final String typeName, final Class<?> type) {
return typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName());
}
}
diff --git a/src/jdk/internal/dynalink/beans/StaticClass.java b/src/jdk/internal/dynalink/beans/StaticClass.java
index 5008c211..f70f2647 100644
--- a/src/jdk/internal/dynalink/beans/StaticClass.java
+++ b/src/jdk/internal/dynalink/beans/StaticClass.java
@@ -96,7 +96,7 @@ import java.io.Serializable;
public class StaticClass implements Serializable {
private static final ClassValue<StaticClass> staticClasses = new ClassValue<StaticClass>() {
@Override
- protected StaticClass computeValue(Class<?> type) {
+ protected StaticClass computeValue(final Class<?> type) {
return new StaticClass(type);
}
};
@@ -105,7 +105,7 @@ public class StaticClass implements Serializable {
private final Class<?> clazz;
- /*private*/ StaticClass(Class<?> clazz) {
+ /*private*/ StaticClass(final Class<?> clazz) {
clazz.getClass(); // NPE check
this.clazz = clazz;
}
@@ -115,7 +115,7 @@ public class StaticClass implements Serializable {
* @param clazz the class for which the static facet is requested.
* @return the {@link StaticClass} instance representing the specified class.
*/
- public static StaticClass forClass(Class<?> clazz) {
+ public static StaticClass forClass(final Class<?> clazz) {
return staticClasses.get(clazz);
}
diff --git a/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java b/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
index 62ce41a9..8a07c1f1 100644
--- a/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
+++ b/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
@@ -90,14 +90,14 @@ import java.util.HashMap;
import java.util.Map;
class StaticClassIntrospector extends FacetIntrospector {
- StaticClassIntrospector(Class<?> clazz) {
+ StaticClassIntrospector(final Class<?> clazz) {
super(clazz, false);
}
@Override
Map<String, MethodHandle> getInnerClassGetters() {
final Map<String, MethodHandle> map = new HashMap<>();
- for(Class<?> innerClass: membersLookup.getInnerClasses()) {
+ for(final Class<?> innerClass: membersLookup.getInnerClasses()) {
map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class,
StaticClass.forClass(innerClass))));
}
@@ -105,15 +105,15 @@ class StaticClassIntrospector extends FacetIntrospector {
}
@Override
- MethodHandle editMethodHandle(MethodHandle mh) {
+ MethodHandle editMethodHandle(final MethodHandle mh) {
return editStaticMethodHandle(mh);
}
- static MethodHandle editStaticMethodHandle(MethodHandle mh) {
+ static MethodHandle editStaticMethodHandle(final MethodHandle mh) {
return dropReceiver(mh, Object.class);
}
- static MethodHandle editConstructorMethodHandle(MethodHandle cmh) {
+ static MethodHandle editConstructorMethodHandle(final MethodHandle cmh) {
return dropReceiver(cmh, StaticClass.class);
}
diff --git a/src/jdk/internal/dynalink/beans/StaticClassLinker.java b/src/jdk/internal/dynalink/beans/StaticClassLinker.java
index 5f80caea..ab9c884a 100644
--- a/src/jdk/internal/dynalink/beans/StaticClassLinker.java
+++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java
@@ -104,7 +104,7 @@ import jdk.internal.dynalink.support.Lookup;
class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
private static final ClassValue<SingleClassStaticsLinker> linkers = new ClassValue<SingleClassStaticsLinker>() {
@Override
- protected SingleClassStaticsLinker computeValue(Class<?> clazz) {
+ protected SingleClassStaticsLinker computeValue(final Class<?> clazz) {
return new SingleClassStaticsLinker(clazz);
}
};
@@ -112,7 +112,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
private static class SingleClassStaticsLinker extends AbstractJavaLinker {
private final DynamicMethod constructor;
- SingleClassStaticsLinker(Class<?> clazz) {
+ SingleClassStaticsLinker(final Class<?> clazz) {
super(clazz, IS_CLASS.bindTo(clazz));
// Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass
// StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS.
@@ -126,7 +126,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
* @return a dynamic method containing all overloads of a class' public constructor. If the class has no public
* constructors, returns null.
*/
- private static DynamicMethod createConstructorMethod(Class<?> clazz) {
+ private static DynamicMethod createConstructorMethod(final Class<?> clazz) {
if(clazz.isArray()) {
final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType());
return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle(
@@ -144,7 +144,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices)
+ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
throws Exception {
final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices);
if(gi != null) {
@@ -160,22 +160,31 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
}
return null;
}
+
+ @Override
+ SingleDynamicMethod getConstructorMethod(final String signature) {
+ return constructor != null? constructor.getMethodForExactParamTypes(signature) : null;
+ }
+ }
+
+ static Object getConstructorMethod(final Class<?> clazz, final String signature) {
+ return linkers.get(clazz).getConstructorMethod(signature);
}
- static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) {
+ static Collection<String> getReadableStaticPropertyNames(final Class<?> clazz) {
return linkers.get(clazz).getReadablePropertyNames();
}
- static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) {
+ static Collection<String> getWritableStaticPropertyNames(final Class<?> clazz) {
return linkers.get(clazz).getWritablePropertyNames();
}
- static Collection<String> getStaticMethodNames(Class<?> clazz) {
+ static Collection<String> getStaticMethodNames(final Class<?> clazz) {
return linkers.get(clazz).getMethodNames();
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception {
+ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
final Object receiver = request.getReceiver();
if(receiver instanceof StaticClass) {
return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request,
@@ -185,7 +194,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
}
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return type == StaticClass.class;
}
@@ -201,7 +210,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
}
@SuppressWarnings("unused")
- private static boolean isClass(Class<?> clazz, Object obj) {
+ private static boolean isClass(final Class<?> clazz, final Object obj) {
return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz;
}
}
diff --git a/src/jdk/internal/dynalink/linker/GuardedInvocation.java b/src/jdk/internal/dynalink/linker/GuardedInvocation.java
index 26a741e8..00ee9dc7 100644
--- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java
+++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java
@@ -83,6 +83,8 @@
package jdk.internal.dynalink.linker;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@@ -104,7 +106,18 @@ import jdk.internal.dynalink.support.Guards;
public class GuardedInvocation {
private final MethodHandle invocation;
private final MethodHandle guard;
- private final SwitchPoint switchPoint;
+ private final Class<? extends Throwable> exception;
+ private final SwitchPoint[] switchPoints;
+
+ /**
+ * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations.
+ *
+ * @param invocation the method handle representing the invocation. Must not be null.
+ * @throws NullPointerException if invocation is null.
+ */
+ public GuardedInvocation(final MethodHandle invocation) {
+ this(invocation, null, (SwitchPoint)null, null);
+ }
/**
* Creates a new guarded invocation.
@@ -115,8 +128,33 @@ public class GuardedInvocation {
* an unconditional invocation, although that is unusual.
* @throws NullPointerException if invocation is null.
*/
- public GuardedInvocation(MethodHandle invocation, MethodHandle guard) {
- this(invocation, guard, null);
+ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) {
+ this(invocation, guard, (SwitchPoint)null, null);
+ }
+
+ /**
+ * Creates a new guarded invocation.
+ *
+ * @param invocation the method handle representing the invocation. Must not be null.
+ * @param switchPoint the optional switch point that can be used to invalidate this linkage.
+ * @throws NullPointerException if invocation is null.
+ */
+ public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) {
+ this(invocation, null, switchPoint, null);
+ }
+
+ /**
+ * Creates a new guarded invocation.
+ *
+ * @param invocation the method handle representing the invocation. Must not be null.
+ * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
+ * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
+ * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
+ * @param switchPoint the optional switch point that can be used to invalidate this linkage.
+ * @throws NullPointerException if invocation is null.
+ */
+ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) {
+ this(invocation, guard, switchPoint, null);
}
/**
@@ -127,28 +165,38 @@ public class GuardedInvocation {
* it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
* and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
* @param switchPoint the optional switch point that can be used to invalidate this linkage.
+ * @param exception the optional exception type that is expected to be thrown by the invocation and that also
+ * invalidates the linkage.
* @throws NullPointerException if invocation is null.
*/
- public GuardedInvocation(MethodHandle invocation, MethodHandle guard, SwitchPoint switchPoint) {
+ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) {
invocation.getClass(); // NPE check
this.invocation = invocation;
this.guard = guard;
- this.switchPoint = switchPoint;
+ this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
+ this.exception = exception;
}
/**
- * Creates a new guarded invocation.
+ * Creates a new guarded invocation
*
* @param invocation the method handle representing the invocation. Must not be null.
- * @param switchPoint the optional switch point that can be used to invalidate this linkage.
* @param guard the method handle representing the guard. Must have the same method type as the invocation, except
* it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
* and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
+ * @param switchPoints the optional switch points that can be used to invalidate this linkage.
+ * @param exception the optional exception type that is expected to be thrown by the invocation and that also
+ * invalidates the linkage.
* @throws NullPointerException if invocation is null.
*/
- public GuardedInvocation(MethodHandle invocation, SwitchPoint switchPoint, MethodHandle guard) {
- this(invocation, guard, switchPoint);
+ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
+ invocation.getClass(); // NPE check
+ this.invocation = invocation;
+ this.guard = guard;
+ this.switchPoints = switchPoints == null ? null : switchPoints.clone();
+ this.exception = exception;
}
+
/**
* Returns the invocation method handle.
*
@@ -172,8 +220,17 @@ public class GuardedInvocation {
*
* @return the switch point that can be used to invalidate the invocation handle. Can be null.
*/
- public SwitchPoint getSwitchPoint() {
- return switchPoint;
+ public SwitchPoint[] getSwitchPoints() {
+ return switchPoints == null ? null : switchPoints.clone();
+ }
+
+ /**
+ * Returns the exception type that if thrown should be used to invalidate the linkage.
+ *
+ * @return the exception type that if thrown should be used to invalidate the linkage. Can be null.
+ */
+ public Class<? extends Throwable> getException() {
+ return exception;
}
/**
@@ -181,7 +238,15 @@ public class GuardedInvocation {
* @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
*/
public boolean hasBeenInvalidated() {
- return switchPoint != null && switchPoint.hasBeenInvalidated();
+ if (switchPoints == null) {
+ return false;
+ }
+ for (final SwitchPoint sp : switchPoints) {
+ if (sp.hasBeenInvalidated()) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -191,9 +256,9 @@ public class GuardedInvocation {
* @param type the asserted type
* @throws WrongMethodTypeException if the invocation and the guard are not of the expected method type.
*/
- public void assertType(MethodType type) {
+ public void assertType(final MethodType type) {
assertType(invocation, type);
- if(guard != null) {
+ if (guard != null) {
assertType(guard, type.changeReturnType(Boolean.TYPE));
}
}
@@ -205,12 +270,34 @@ public class GuardedInvocation {
* @param newGuard the new guard
* @return a new guarded invocation with the replaced methods and the same switch point as this invocation.
*/
- public GuardedInvocation replaceMethods(MethodHandle newInvocation, MethodHandle newGuard) {
- return new GuardedInvocation(newInvocation, newGuard, switchPoint);
+ public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) {
+ return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception);
}
- private GuardedInvocation replaceMethodsOrThis(MethodHandle newInvocation, MethodHandle newGuard) {
- if(newInvocation == invocation && newGuard == guard) {
+ /**
+ * Add a switchpoint to this guarded invocation
+ * @param newSwitchPoint new switchpoint, or null for nop
+ * @return new guarded invocation with the extra switchpoint
+ */
+ public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
+ if (newSwitchPoint == null) {
+ return this;
+ }
+
+ final SwitchPoint[] newSwitchPoints;
+ if (switchPoints != null) {
+ newSwitchPoints = new SwitchPoint[switchPoints.length + 1];
+ System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length);
+ newSwitchPoints[switchPoints.length] = newSwitchPoint;
+ } else {
+ newSwitchPoints = new SwitchPoint[] { newSwitchPoint };
+ }
+
+ return new GuardedInvocation(invocation, guard, newSwitchPoints, exception);
+ }
+
+ private GuardedInvocation replaceMethodsOrThis(final MethodHandle newInvocation, final MethodHandle newGuard) {
+ if (newInvocation == invocation && newGuard == guard) {
return this;
}
return replaceMethods(newInvocation, newGuard);
@@ -223,7 +310,7 @@ public class GuardedInvocation {
* @param newType the new type of the invocation.
* @return a guarded invocation with the new type applied to it.
*/
- public GuardedInvocation asType(MethodType newType) {
+ public GuardedInvocation asType(final MethodType newType) {
return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType));
}
@@ -235,19 +322,33 @@ public class GuardedInvocation {
* @param newType the new type of the invocation.
* @return a guarded invocation with the new type applied to it.
*/
- public GuardedInvocation asType(LinkerServices linkerServices, MethodType newType) {
+ public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) {
return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null :
Guards.asType(linkerServices, guard, newType));
}
/**
+ * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was
+ * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it
+ * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the
+ * invocation doesn't change its type, returns this object.
+ * @param linkerServices the linker services to use for the conversion
+ * @param newType the new type of the invocation.
+ * @return a guarded invocation with the new type applied to it.
+ */
+ public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) {
+ return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null :
+ Guards.asType(linkerServices, guard, newType));
+ }
+
+ /**
* Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
* and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the
* required type, returns this object.
* @param desc a call descriptor whose method type is adapted.
* @return a guarded invocation with the new type applied to it.
*/
- public GuardedInvocation asType(CallSiteDescriptor desc) {
+ public GuardedInvocation asType(final CallSiteDescriptor desc) {
return asType(desc.getMethodType());
}
@@ -257,7 +358,7 @@ public class GuardedInvocation {
* @param filters the argument filters
* @return a filtered invocation
*/
- public GuardedInvocation filterArguments(int pos, MethodHandle... filters) {
+ public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
MethodHandles.filterArguments(guard, pos, filters));
}
@@ -268,7 +369,7 @@ public class GuardedInvocation {
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
- public GuardedInvocation dropArguments(int pos, List<Class<?>> valueTypes) {
+ public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
MethodHandles.dropArguments(guard, pos, valueTypes));
}
@@ -279,7 +380,7 @@ public class GuardedInvocation {
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
- public GuardedInvocation dropArguments(int pos, Class<?>... valueTypes) {
+ public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
MethodHandles.dropArguments(guard, pos, valueTypes));
}
@@ -290,23 +391,50 @@ public class GuardedInvocation {
* @param fallback the fallback method handle in case switchpoint is invalidated or guard returns false.
* @return a composite method handle.
*/
- public MethodHandle compose(MethodHandle fallback) {
- return compose(fallback, fallback);
+ public MethodHandle compose(final MethodHandle fallback) {
+ return compose(fallback, fallback, fallback);
}
/**
* Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
* @param switchpointFallback the fallback method handle in case switchpoint is invalidated.
* @param guardFallback the fallback method handle in case guard returns false.
+ * @param catchFallback the fallback method in case the exception handler triggers
* @return a composite method handle.
*/
- public MethodHandle compose(MethodHandle switchpointFallback, MethodHandle guardFallback) {
+ public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
final MethodHandle guarded =
- guard == null ? invocation : MethodHandles.guardWithTest(guard, invocation, guardFallback);
- return switchPoint == null ? guarded : switchPoint.guardWithTest(guarded, switchpointFallback);
+ guard == null ?
+ invocation :
+ MethodHandles.guardWithTest(
+ guard,
+ invocation,
+ guardFallback);
+
+ final MethodHandle catchGuarded =
+ exception == null ?
+ guarded :
+ MH.catchException(
+ guarded,
+ exception,
+ MethodHandles.dropArguments(
+ catchFallback,
+ 0,
+ exception));
+
+ if (switchPoints == null) {
+ return catchGuarded;
+ }
+
+ MethodHandle spGuarded = catchGuarded;
+ for (final SwitchPoint sp : switchPoints) {
+ spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
+ }
+
+ return spGuarded;
}
- private static void assertType(MethodHandle mh, MethodType type) {
+ private static void assertType(final MethodHandle mh, final MethodType type) {
if(!mh.type().equals(type)) {
throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());
}
diff --git a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
index 9baed7c0..88357ff0 100644
--- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
+++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
@@ -83,19 +83,35 @@
package jdk.internal.dynalink.linker;
+/**
+ * Guarded type conversion
+ */
public class GuardedTypeConversion {
private final GuardedInvocation conversionInvocation;
private final boolean cacheable;
+ /**
+ * Constructor
+ * @param conversionInvocation guarded invocation for this type conversion
+ * @param cacheable is this invocation cacheable
+ */
public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) {
this.conversionInvocation = conversionInvocation;
this.cacheable = cacheable;
}
+ /**
+ * Get the invocation
+ * @return invocation
+ */
public GuardedInvocation getConversionInvocation() {
return conversionInvocation;
}
+ /**
+ * Check if invocation is cacheable
+ * @return true if cachable, false otherwise
+ */
public boolean isCacheable() {
return cacheable;
}
diff --git a/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java b/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
index 2cd0d0f0..82a36197 100644
--- a/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
+++ b/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
@@ -101,10 +101,16 @@ public interface GuardingDynamicLinker {
* @return a guarded invocation with a method handle suitable for the arguments, as well as a guard condition that
* if fails should trigger relinking. Must return null if it can't resolve the invocation. If the returned
* invocation is unconditional (which is actually quite rare), the guard in the return value can be null. The
- * invocation can also have a switch point for asynchronous invalidation of the linkage. If the linker does not
- * recognize any native language runtime contexts in arguments, or does recognize its own, but receives a call site
- * descriptor without its recognized context in the arguments, it should invoke
- * {@link LinkRequest#withoutRuntimeContext()} and link for that.
+ * invocation can also have a switch point for asynchronous invalidation of the linkage, as well as a
+ * {@link Throwable} subclass that describes an expected exception condition that also triggers relinking (often it
+ * is faster to rely on an infrequent but expected {@link ClassCastException} than on an always evaluated
+ * {@code instanceof} guard). If the linker does not recognize any native language runtime contexts in arguments, or
+ * does recognize its own, but receives a call site descriptor without its recognized context in the arguments, it
+ * should invoke {@link LinkRequest#withoutRuntimeContext()} and link for that. While the linker must produce an
+ * invocation with parameter types matching those in the call site descriptor of the link request, it should not try
+ * to match the return type expected at the call site except when it can do it with only the conversions that lose
+ * neither precision nor magnitude, see {@link LinkerServices#asTypeLosslessReturn(java.lang.invoke.MethodHandle,
+ * java.lang.invoke.MethodType)}.
* @throws Exception if the operation fails for whatever reason
*/
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices)
diff --git a/src/jdk/internal/dynalink/linker/LinkRequest.java b/src/jdk/internal/dynalink/linker/LinkRequest.java
index 1a82a4fa..63501cdc 100644
--- a/src/jdk/internal/dynalink/linker/LinkRequest.java
+++ b/src/jdk/internal/dynalink/linker/LinkRequest.java
@@ -101,6 +101,17 @@ public interface LinkRequest {
public CallSiteDescriptor getCallSiteDescriptor();
/**
+ * Returns the call site token for the call site being linked. This token is an opaque object that is guaranteed to
+ * have different identity for different call sites, and is also guaranteed to not become weakly reachable before
+ * the call site does and to become weakly reachable some time after the call site does. This makes it ideal as a
+ * candidate for a key in a weak hash map in which a linker might want to keep per-call site linking state (usually
+ * profiling information).
+ *
+ * @return the call site token for the call site being linked.
+ */
+ public Object getCallSiteToken();
+
+ /**
* Returns the arguments for the invocation being linked. The returned array is a clone; modifications to it won't
* affect the arguments in this request.
*
@@ -116,6 +127,17 @@ public interface LinkRequest {
public Object getReceiver();
/**
+ * Returns the number of times this callsite has been linked/relinked. This can be useful if you want to
+ * change e.g. exception based relinking to guard based relinking. It's probably not a good idea to keep,
+ * for example, expensive exception throwing relinkage based on failed type checks/ClassCastException in
+ * a nested callsite tree where the exception is thrown repeatedly for the common case. There it would be
+ * much more performant to use exact type guards instead.
+ *
+ * @return link count for call site
+ */
+ public int getLinkCount();
+
+ /**
* Returns true if the call site is considered unstable, that is, it has been relinked more times than was
* specified in {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)}. Linkers should use this as a
* hint to prefer producing linkage that is more stable (its guard fails less frequently), even if that assumption
diff --git a/src/jdk/internal/dynalink/linker/LinkerServices.java b/src/jdk/internal/dynalink/linker/LinkerServices.java
index deaf820f..9e35d7f6 100644
--- a/src/jdk/internal/dynalink/linker/LinkerServices.java
+++ b/src/jdk/internal/dynalink/linker/LinkerServices.java
@@ -87,7 +87,9 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.DynamicLinker;
+import jdk.internal.dynalink.DynamicLinkerFactory;
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
+import jdk.internal.dynalink.support.TypeUtilities;
/**
* Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns
@@ -103,18 +105,34 @@ public interface LinkerServices {
* parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
* wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
* it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
- * provided by {@link GuardingTypeConverterFactory} implementations. It doesn't use language-specific conversions on
- * the return type.
+ * provided by {@link GuardingTypeConverterFactory} implementations.
*
* @param handle target method handle
* @param fromType the types of source arguments
- * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
- * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
- * {@link GuardingTypeConverterFactory} produced type converters as filters.
+ * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)},
+ * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}, and
+ * {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)} with
+ * {@link GuardingTypeConverterFactory}-produced type converters as filters.
*/
public MethodHandle asType(MethodHandle handle, MethodType fromType);
/**
+ * Similar to {@link #asType(MethodHandle, MethodType)} except it only converts the return type of the method handle
+ * when it can be done using a conversion that loses neither precision nor magnitude, otherwise it leaves it
+ * unchanged. The idea is that other conversions should not be performed by individual linkers, but instead the
+ * {@link DynamicLinkerFactory#setPrelinkFilter(jdk.internal.dynalink.GuardedInvocationFilter) pre-link filter of
+ * the dynamic linker} should implement the strategy of dealing with potentially lossy return type conversions in a
+ * manner specific to the language runtime.
+ *
+ * @param handle target method handle
+ * @param fromType the types of source arguments
+ * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, and
+ * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
+ * {@link GuardingTypeConverterFactory}-produced type converters as filters.
+ */
+ public MethodHandle asTypeLosslessReturn(MethodHandle handle, MethodType fromType);
+
+ /**
* Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
* case it will return an identity conversion (that might fail for some values at runtime). You rarely need to use
* this method directly; you should mostly rely on {@link #asType(MethodHandle, MethodType)} instead. You really
@@ -161,4 +179,23 @@ public interface LinkerServices {
* conversion.
*/
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
+
+ /**
+ * If we could just use Java 8 constructs, then {@code asTypeSafeReturn} would be a method with default
+ * implementation. Since we can't do that, we extract common default implementations into this static class.
+ */
+ public static class Implementation {
+ /**
+ * Default implementation for {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}.
+ * @param linkerServices the linker services that delegates to this implementation
+ * @param handle the passed handle
+ * @param fromType the passed type
+ * @return the converted method handle, as per the {@code asTypeSafeReturn} semantics.
+ */
+ public static MethodHandle asTypeLosslessReturn(final LinkerServices linkerServices, final MethodHandle handle, final MethodType fromType) {
+ final Class<?> handleReturnType = handle.type().returnType();
+ return linkerServices.asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ?
+ fromType : fromType.changeReturnType(handleReturnType));
+ }
+ }
}
diff --git a/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java b/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java
new file mode 100644
index 00000000..f270c5fc
--- /dev/null
+++ b/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+ Copyright 2014 Attila Szegedi
+
+ Licensed under both the Apache License, Version 2.0 (the "Apache License")
+ and the BSD License (the "BSD License"), with licensee being free to
+ choose either of the two at their discretion.
+
+ You may not use this file except in compliance with either the Apache
+ License or the BSD License.
+
+ If you choose to use this file in compliance with the Apache License, the
+ following notice applies to you:
+
+ You may obtain a copy of the Apache License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ If you choose to use this file in compliance with the BSD License, the
+ following notice applies to you:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.internal.dynalink.linker;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+
+/**
+ * Interface for objects representing a strategy for converting a method handle to a new type.
+ */
+public interface MethodTypeConversionStrategy {
+ /**
+ * Converts a method handle to a new type.
+ * @param target target method handle
+ * @param newType new type
+ * @return target converted to the new type.
+ */
+ public MethodHandle asType(final MethodHandle target, final MethodType newType);
+}
diff --git a/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java b/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
index 3161cf50..6bcbbbb3 100644
--- a/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
+++ b/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
@@ -106,7 +106,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
return obj instanceof CallSiteDescriptor && equals((CallSiteDescriptor)obj);
}
@@ -115,7 +115,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
* @param csd the other call site descriptor.
* @return true if they are equal.
*/
- public boolean equals(CallSiteDescriptor csd) {
+ public boolean equals(final CallSiteDescriptor csd) {
if(csd == null) {
return false;
}
@@ -165,7 +165,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
return l + c - 1;
}
- private StringBuilder appendName(StringBuilder b) {
+ private StringBuilder appendName(final StringBuilder b) {
b.append(getNameToken(0));
final int c = getNameTokenCount();
for(int i = 1; i < c; ++i) {
@@ -174,7 +174,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
return b;
}
- private static boolean lookupsEqual(Lookup l1, Lookup l2) {
+ private static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
if(l1 == l2) {
return true;
}
diff --git a/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java b/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
index c05d35e0..e01880e5 100644
--- a/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
+++ b/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
@@ -100,7 +100,7 @@ public abstract class AbstractRelinkableCallSite extends MutableCallSite impleme
* Creates a new relinkable call site.
* @param descriptor the descriptor for this call site
*/
- protected AbstractRelinkableCallSite(CallSiteDescriptor descriptor) {
+ protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) {
super(descriptor.getMethodType());
this.descriptor = descriptor;
}
@@ -111,7 +111,7 @@ public abstract class AbstractRelinkableCallSite extends MutableCallSite impleme
}
@Override
- public void initialize(MethodHandle relinkAndInvoke) {
+ public void initialize(final MethodHandle relinkAndInvoke) {
setTarget(relinkAndInvoke);
}
}
diff --git a/src/jdk/internal/dynalink/support/AutoDiscovery.java b/src/jdk/internal/dynalink/support/AutoDiscovery.java
index 29093659..ba318610 100644
--- a/src/jdk/internal/dynalink/support/AutoDiscovery.java
+++ b/src/jdk/internal/dynalink/support/AutoDiscovery.java
@@ -116,14 +116,14 @@ public class AutoDiscovery {
* @return a list of guarding dynamic linkers available through the specified class loader. Can be zero-length list
* but not null.
*/
- public static List<GuardingDynamicLinker> loadLinkers(ClassLoader cl) {
+ public static List<GuardingDynamicLinker> loadLinkers(final ClassLoader cl) {
return getLinkers(ServiceLoader.load(GuardingDynamicLinker.class, cl));
}
/**
* I can't believe there's no Collections API for making a List given an Iterator...
*/
- private static <T> List<T> getLinkers(ServiceLoader<T> loader) {
+ private static <T> List<T> getLinkers(final ServiceLoader<T> loader) {
final List<T> list = new LinkedList<>();
for(final T linker: loader) {
list.add(linker);
diff --git a/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java b/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
index 7a2700e1..07abb6c3 100644
--- a/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
+++ b/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
@@ -105,12 +105,12 @@ public class BottomGuardingDynamicLinker implements TypeBasedGuardingDynamicLink
}
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return false;
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) {
return null;
}
}
diff --git a/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java b/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
index b0039d21..9cbd5f04 100644
--- a/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
+++ b/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
@@ -86,6 +86,7 @@ package jdk.internal.dynalink.support;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
@@ -103,7 +104,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
* @author Attila Szegedi
*/
public class CallSiteDescriptorFactory {
- private static final WeakHashMap<CallSiteDescriptor, WeakReference<CallSiteDescriptor>> publicDescs =
+ private static final WeakHashMap<CallSiteDescriptor, Reference<CallSiteDescriptor>> publicDescs =
new WeakHashMap<>();
@@ -121,7 +122,7 @@ public class CallSiteDescriptorFactory {
* @return a call site descriptor representing the input. Note that although the method name is "create", it will
* in fact return a weakly-referenced canonical instance.
*/
- public static CallSiteDescriptor create(Lookup lookup, String name, MethodType methodType) {
+ public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) {
name.getClass(); // NPE check
methodType.getClass(); // NPE check
lookup.getClass(); // NPE check
@@ -134,19 +135,28 @@ public class CallSiteDescriptorFactory {
static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
synchronized(publicDescs) {
- final WeakReference<CallSiteDescriptor> ref = publicDescs.get(desc);
+ final Reference<CallSiteDescriptor> ref = publicDescs.get(desc);
if(ref != null) {
final CallSiteDescriptor canonical = ref.get();
if(canonical != null) {
return canonical;
}
}
- publicDescs.put(desc, new WeakReference<>(desc));
+ publicDescs.put(desc, createReference(desc));
}
return desc;
}
- private static CallSiteDescriptor createPublicCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
+ /**
+ * Override this to use a different kind of references for the cache
+ * @param desc desc
+ * @return reference
+ */
+ protected static Reference<CallSiteDescriptor> createReference(final CallSiteDescriptor desc) {
+ return new WeakReference<>(desc);
+ }
+
+ private static CallSiteDescriptor createPublicCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) {
final int l = tokenizedName.length;
if(l > 0 && tokenizedName[0] == "dyn") {
if(l == 2) {
@@ -158,7 +168,7 @@ public class CallSiteDescriptorFactory {
return new DefaultCallSiteDescriptor(tokenizedName, methodType);
}
- private static boolean isPublicLookup(Lookup lookup) {
+ private static boolean isPublicLookup(final Lookup lookup) {
return lookup == MethodHandles.publicLookup();
}
@@ -169,7 +179,7 @@ public class CallSiteDescriptorFactory {
* @param name the composite name consisting of colon-separated, possibly mangled tokens.
* @return an array of tokens
*/
- public static String[] tokenizeName(String name) {
+ public static String[] tokenizeName(final String name) {
final StringTokenizer tok = new StringTokenizer(name, CallSiteDescriptor.TOKEN_DELIMITER);
final String[] tokens = new String[tok.countTokens()];
for(int i = 0; i < tokens.length; ++i) {
@@ -188,7 +198,7 @@ public class CallSiteDescriptorFactory {
* @param desc the call site descriptor with the operation
* @return a list of tokens
*/
- public static List<String> tokenizeOperators(CallSiteDescriptor desc) {
+ public static List<String> tokenizeOperators(final CallSiteDescriptor desc) {
final String ops = desc.getNameToken(CallSiteDescriptor.OPERATOR);
final StringTokenizer tok = new StringTokenizer(ops, CallSiteDescriptor.OPERATOR_DELIMITER);
final int count = tok.countTokens();
@@ -210,7 +220,7 @@ public class CallSiteDescriptorFactory {
* @param end index of the first parameter to not remove
* @return a new call site descriptor with modified method type
*/
- public static CallSiteDescriptor dropParameterTypes(CallSiteDescriptor desc, int start, int end) {
+ public static CallSiteDescriptor dropParameterTypes(final CallSiteDescriptor desc, final int start, final int end) {
return desc.changeMethodType(desc.getMethodType().dropParameterTypes(start, end));
}
@@ -222,7 +232,7 @@ public class CallSiteDescriptorFactory {
* @param nptype the new parameter type
* @return a new call site descriptor with modified method type
*/
- public static CallSiteDescriptor changeParameterType(CallSiteDescriptor desc, int num, Class<?> nptype) {
+ public static CallSiteDescriptor changeParameterType(final CallSiteDescriptor desc, final int num, final Class<?> nptype) {
return desc.changeMethodType(desc.getMethodType().changeParameterType(num, nptype));
}
@@ -233,7 +243,7 @@ public class CallSiteDescriptorFactory {
* @param nrtype the new return type
* @return a new call site descriptor with modified method type
*/
- public static CallSiteDescriptor changeReturnType(CallSiteDescriptor desc, Class<?> nrtype) {
+ public static CallSiteDescriptor changeReturnType(final CallSiteDescriptor desc, final Class<?> nrtype) {
return desc.changeMethodType(desc.getMethodType().changeReturnType(nrtype));
}
@@ -245,7 +255,7 @@ public class CallSiteDescriptorFactory {
* @param ptypesToInsert the new types to insert
* @return a new call site descriptor with modified method type
*/
- public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, Class<?>... ptypesToInsert) {
+ public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final Class<?>... ptypesToInsert) {
return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
}
@@ -257,7 +267,7 @@ public class CallSiteDescriptorFactory {
* @param ptypesToInsert the new types to insert
* @return a new call site descriptor with modified method type
*/
- public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, List<Class<?>> ptypesToInsert) {
+ public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final List<Class<?>> ptypesToInsert) {
return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
}
}
diff --git a/src/jdk/internal/dynalink/support/ClassMap.java b/src/jdk/internal/dynalink/support/ClassMap.java
index d85b21d0..758349b8 100644
--- a/src/jdk/internal/dynalink/support/ClassMap.java
+++ b/src/jdk/internal/dynalink/support/ClassMap.java
@@ -110,7 +110,7 @@ public abstract class ClassMap<T> {
*
* @param classLoader the classloader that determines strong referenceability.
*/
- protected ClassMap(ClassLoader classLoader) {
+ protected ClassMap(final ClassLoader classLoader) {
this.classLoader = classLoader;
}
diff --git a/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java b/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
index 44f5c4b3..007ab98d 100644
--- a/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
+++ b/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
@@ -109,16 +109,16 @@ public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker, Se
*
* @param linkers a list of component linkers.
*/
- public CompositeGuardingDynamicLinker(Iterable<? extends GuardingDynamicLinker> linkers) {
+ public CompositeGuardingDynamicLinker(final Iterable<? extends GuardingDynamicLinker> linkers) {
final List<GuardingDynamicLinker> l = new LinkedList<>();
- for(GuardingDynamicLinker linker: linkers) {
+ for(final GuardingDynamicLinker linker: linkers) {
l.add(linker);
}
this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]);
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
throws Exception {
for(final GuardingDynamicLinker linker: linkers) {
final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
diff --git a/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java b/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
index 180ab0c6..d1ff0280 100644
--- a/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
+++ b/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
@@ -111,8 +111,8 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
private final TypeBasedGuardingDynamicLinker[] linkers;
private final List<TypeBasedGuardingDynamicLinker>[] singletonLinkers;
- @SuppressWarnings("unchecked")
- ClassToLinker(TypeBasedGuardingDynamicLinker[] linkers) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) {
this.linkers = linkers;
singletonLinkers = new List[linkers.length];
for(int i = 0; i < linkers.length; ++i) {
@@ -120,8 +120,9 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
}
}
+ @SuppressWarnings("fallthrough")
@Override
- protected List<TypeBasedGuardingDynamicLinker> computeValue(Class<?> clazz) {
+ protected List<TypeBasedGuardingDynamicLinker> computeValue(final Class<?> clazz) {
List<TypeBasedGuardingDynamicLinker> list = NO_LINKER;
for(int i = 0; i < linkers.length; ++i) {
final TypeBasedGuardingDynamicLinker linker = linkers[i];
@@ -134,7 +135,6 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
case 1: {
list = new LinkedList<>(list);
}
- //$FALL-THROUGH$
default: {
list.add(linker);
}
@@ -152,27 +152,27 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
*
* @param linkers the component linkers
*/
- public CompositeTypeBasedGuardingDynamicLinker(Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
+ public CompositeTypeBasedGuardingDynamicLinker(final Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
- for(TypeBasedGuardingDynamicLinker linker: linkers) {
+ for(final TypeBasedGuardingDynamicLinker linker: linkers) {
l.add(linker);
}
this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
}
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return !classToLinker.get(type).isEmpty();
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
throws Exception {
final Object obj = linkRequest.getReceiver();
if(obj == null) {
return null;
}
- for(TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
+ for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
if(invocation != null) {
return invocation;
@@ -189,10 +189,10 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
* @param linkers the list of linkers to optimize
* @return the optimized list
*/
- public static List<GuardingDynamicLinker> optimize(Iterable<? extends GuardingDynamicLinker> linkers) {
+ public static List<GuardingDynamicLinker> optimize(final Iterable<? extends GuardingDynamicLinker> linkers) {
final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
- for(GuardingDynamicLinker linker: linkers) {
+ for(final GuardingDynamicLinker linker: linkers) {
if(linker instanceof TypeBasedGuardingDynamicLinker) {
tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
} else {
@@ -204,8 +204,8 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
return llinkers;
}
- private static void addTypeBased(List<GuardingDynamicLinker> llinkers,
- List<TypeBasedGuardingDynamicLinker> tblinkers) {
+ private static void addTypeBased(final List<GuardingDynamicLinker> llinkers,
+ final List<TypeBasedGuardingDynamicLinker> tblinkers) {
switch(tblinkers.size()) {
case 0: {
break;
diff --git a/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java b/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
index 46d4fc8b..878d9aa0 100644
--- a/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
+++ b/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
@@ -98,7 +98,7 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor {
private final String[] tokenizedName;
private final MethodType methodType;
- DefaultCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
+ DefaultCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) {
this.tokenizedName = tokenizedName;
this.methodType = methodType;
}
@@ -109,10 +109,10 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor {
}
@Override
- public String getNameToken(int i) {
+ public String getNameToken(final int i) {
try {
return tokenizedName[i];
- } catch(ArrayIndexOutOfBoundsException e) {
+ } catch(final ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
@@ -127,7 +127,7 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor {
}
@Override
- public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+ public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new DefaultCallSiteDescriptor(tokenizedName,
newMethodType));
}
diff --git a/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java b/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java
new file mode 100644
index 00000000..ad9679f6
--- /dev/null
+++ b/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+ Copyright 2009-2013 Attila Szegedi
+
+ Licensed under both the Apache License, Version 2.0 (the "Apache License")
+ and the BSD License (the "BSD License"), with licensee being free to
+ choose either of the two at their discretion.
+
+ You may not use this file except in compliance with either the Apache
+ License or the BSD License.
+
+ If you choose to use this file in compliance with the Apache License, the
+ following notice applies to you:
+
+ You may obtain a copy of the Apache License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ If you choose to use this file in compliance with the BSD License, the
+ following notice applies to you:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.internal.dynalink.support;
+
+import jdk.internal.dynalink.GuardedInvocationFilter;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+
+/**
+ * Default filter for guarded invocation pre link filtering
+ */
+public class DefaultPrelinkFilter implements GuardedInvocationFilter {
+ @Override
+ public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
+ return inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType());
+ }
+}
diff --git a/src/jdk/internal/dynalink/support/Guards.java b/src/jdk/internal/dynalink/support/Guards.java
index 42aa6758..02f3045d 100644
--- a/src/jdk/internal/dynalink/support/Guards.java
+++ b/src/jdk/internal/dynalink/support/Guards.java
@@ -113,7 +113,7 @@ public class Guards {
* @return a method handle testing whether its first argument is of the specified class.
*/
@SuppressWarnings("boxing")
- public static MethodHandle isOfClass(Class<?> clazz, MethodType type) {
+ public static MethodHandle isOfClass(final Class<?> clazz, final MethodType type) {
final Class<?> declaredType = type.parameterType(0);
if(clazz == declaredType) {
LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -135,7 +135,7 @@ public class Guards {
* @param type the method type
* @return a method handle testing whether its first argument is of the specified class or subclass.
*/
- public static MethodHandle isInstance(Class<?> clazz, MethodType type) {
+ public static MethodHandle isInstance(final Class<?> clazz, final MethodType type) {
return isInstance(clazz, 0, type);
}
@@ -150,7 +150,7 @@ public class Guards {
* @return a method handle testing whether its first argument is of the specified class or subclass.
*/
@SuppressWarnings("boxing")
- public static MethodHandle isInstance(Class<?> clazz, int pos, MethodType type) {
+ public static MethodHandle isInstance(final Class<?> clazz, final int pos, final MethodType type) {
final Class<?> declaredType = type.parameterType(pos);
if(clazz.isAssignableFrom(declaredType)) {
LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -172,7 +172,7 @@ public class Guards {
* the arguments are ignored.
*/
@SuppressWarnings("boxing")
- public static MethodHandle isArray(int pos, MethodType type) {
+ public static MethodHandle isArray(final int pos, final MethodType type) {
final Class<?> declaredType = type.parameterType(pos);
if(declaredType.isArray()) {
LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -193,7 +193,7 @@ public class Guards {
* @param referredLoader the referred class loader
* @return true if it is safe to strongly reference the class
*/
- public static boolean canReferenceDirectly(ClassLoader referrerLoader, final ClassLoader referredLoader) {
+ public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) {
if(referredLoader == null) {
// Can always refer directly to a system class
return true;
@@ -215,7 +215,7 @@ public class Guards {
return false;
}
- private static MethodHandle getClassBoundArgumentTest(MethodHandle test, Class<?> clazz, int pos, MethodType type) {
+ private static MethodHandle getClassBoundArgumentTest(final MethodHandle test, final Class<?> clazz, final int pos, final MethodType type) {
// Bind the class to the first argument of the test
return asType(test.bindTo(clazz), pos, type);
}
@@ -227,7 +227,7 @@ public class Guards {
* @param type the type to adapt the method handle to
* @return the adapted method handle
*/
- public static MethodHandle asType(MethodHandle test, MethodType type) {
+ public static MethodHandle asType(final MethodHandle test, final MethodType type) {
return test.asType(getTestType(test, type));
}
@@ -239,16 +239,16 @@ public class Guards {
* @param type the type to adapt the method handle to
* @return the adapted method handle
*/
- public static MethodHandle asType(LinkerServices linkerServices, MethodHandle test, MethodType type) {
+ public static MethodHandle asType(final LinkerServices linkerServices, final MethodHandle test, final MethodType type) {
return linkerServices.asType(test, getTestType(test, type));
}
- private static MethodType getTestType(MethodHandle test, MethodType type) {
+ private static MethodType getTestType(final MethodHandle test, final MethodType type) {
return type.dropParameterTypes(test.type().parameterCount(),
type.parameterCount()).changeReturnType(boolean.class);
}
- private static MethodHandle asType(MethodHandle test, int pos, MethodType type) {
+ private static MethodHandle asType(final MethodHandle test, final int pos, final MethodType type) {
assert test != null;
assert type != null;
assert type.parameterCount() > 0;
@@ -283,7 +283,7 @@ public class Guards {
* @param clazz the class to test for.
* @return the desired guard method.
*/
- public static MethodHandle getClassGuard(Class<?> clazz) {
+ public static MethodHandle getClassGuard(final Class<?> clazz) {
return IS_OF_CLASS.bindTo(clazz);
}
@@ -292,7 +292,7 @@ public class Guards {
* @param clazz the class to test for.
* @return the desired guard method.
*/
- public static MethodHandle getInstanceOfGuard(Class<?> clazz) {
+ public static MethodHandle getInstanceOfGuard(final Class<?> clazz) {
return IS_INSTANCE.bindTo(clazz);
}
@@ -301,7 +301,7 @@ public class Guards {
* @param obj the object used as referential identity test
* @return the desired guard method.
*/
- public static MethodHandle getIdentityGuard(Object obj) {
+ public static MethodHandle getIdentityGuard(final Object obj) {
return IS_IDENTICAL.bindTo(obj);
}
@@ -322,39 +322,39 @@ public class Guards {
}
@SuppressWarnings("unused")
- private static boolean isNull(Object obj) {
+ private static boolean isNull(final Object obj) {
return obj == null;
}
@SuppressWarnings("unused")
- private static boolean isNotNull(Object obj) {
+ private static boolean isNotNull(final Object obj) {
return obj != null;
}
@SuppressWarnings("unused")
- private static boolean isArray(Object o) {
+ private static boolean isArray(final Object o) {
return o != null && o.getClass().isArray();
}
@SuppressWarnings("unused")
- private static boolean isOfClass(Class<?> c, Object o) {
+ private static boolean isOfClass(final Class<?> c, final Object o) {
return o != null && o.getClass() == c;
}
@SuppressWarnings("unused")
- private static boolean isIdentical(Object o1, Object o2) {
+ private static boolean isIdentical(final Object o1, final Object o2) {
return o1 == o2;
}
- private static MethodHandle constantTrue(MethodType type) {
+ private static MethodHandle constantTrue(final MethodType type) {
return constantBoolean(Boolean.TRUE, type);
}
- private static MethodHandle constantFalse(MethodType type) {
+ private static MethodHandle constantFalse(final MethodType type) {
return constantBoolean(Boolean.FALSE, type);
}
- private static MethodHandle constantBoolean(Boolean value, MethodType type) {
+ private static MethodHandle constantBoolean(final Boolean value, final MethodType type) {
return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value),
type.changeReturnType(Boolean.TYPE));
}
diff --git a/src/jdk/internal/dynalink/support/LinkRequestImpl.java b/src/jdk/internal/dynalink/support/LinkRequestImpl.java
index c2b0092b..2d4c0b18 100644
--- a/src/jdk/internal/dynalink/support/LinkRequestImpl.java
+++ b/src/jdk/internal/dynalink/support/LinkRequestImpl.java
@@ -95,18 +95,24 @@ import jdk.internal.dynalink.linker.LinkRequest;
public class LinkRequestImpl implements LinkRequest {
private final CallSiteDescriptor callSiteDescriptor;
+ private final Object callSiteToken;
private final Object[] arguments;
private final boolean callSiteUnstable;
+ private final int linkCount;
/**
* Creates a new link request.
*
* @param callSiteDescriptor the descriptor for the call site being linked
+ * @param callSiteToken the opaque token for the call site being linked.
+ * @param linkCount how many times this callsite has been linked/relinked
* @param callSiteUnstable true if the call site being linked is considered unstable
* @param arguments the arguments for the invocation
*/
- public LinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable, Object... arguments) {
+ public LinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, final int linkCount, final boolean callSiteUnstable, final Object... arguments) {
this.callSiteDescriptor = callSiteDescriptor;
+ this.callSiteToken = callSiteToken;
+ this.linkCount = linkCount;
this.callSiteUnstable = callSiteUnstable;
this.arguments = arguments;
}
@@ -127,17 +133,27 @@ public class LinkRequestImpl implements LinkRequest {
}
@Override
+ public Object getCallSiteToken() {
+ return callSiteToken;
+ }
+
+ @Override
public boolean isCallSiteUnstable() {
return callSiteUnstable;
}
@Override
+ public int getLinkCount() {
+ return linkCount;
+ }
+
+ @Override
public LinkRequest withoutRuntimeContext() {
return this;
}
@Override
- public LinkRequest replaceArguments(CallSiteDescriptor newCallSiteDescriptor, Object[] newArguments) {
- return new LinkRequestImpl(newCallSiteDescriptor, callSiteUnstable, newArguments);
+ public LinkRequest replaceArguments(final CallSiteDescriptor newCallSiteDescriptor, final Object[] newArguments) {
+ return new LinkRequestImpl(newCallSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, newArguments);
}
}
diff --git a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
index 3b8e7b46..38d93c84 100644
--- a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
+++ b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
@@ -117,27 +117,32 @@ public class LinkerServicesImpl implements LinkerServices {
}
@Override
- public boolean canConvert(Class<?> from, Class<?> to) {
+ public boolean canConvert(final Class<?> from, final Class<?> to) {
return typeConverterFactory.canConvert(from, to);
}
@Override
- public MethodHandle asType(MethodHandle handle, MethodType fromType) {
+ public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
return typeConverterFactory.asType(handle, fromType);
}
@Override
- public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
+ public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
+ return Implementation.asTypeLosslessReturn(this, handle, fromType);
+ }
+
+ @Override
+ public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
return typeConverterFactory.getTypeConverter(sourceType, targetType);
}
@Override
- public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
+ public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2);
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception {
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception {
final LinkRequest prevLinkRequest = threadLinkRequest.get();
threadLinkRequest.set(linkRequest);
try {
@@ -154,7 +159,7 @@ public class LinkerServicesImpl implements LinkerServices {
* permission.
*/
public static LinkRequest getCurrentLinkRequest() {
- SecurityManager sm = System.getSecurityManager();
+ final SecurityManager sm = System.getSecurityManager();
if(sm != null) {
sm.checkPermission(GET_CURRENT_LINK_REQUEST);
}
diff --git a/src/jdk/internal/dynalink/support/Lookup.java b/src/jdk/internal/dynalink/support/Lookup.java
index ba4ff77c..ab64ebb1 100644
--- a/src/jdk/internal/dynalink/support/Lookup.java
+++ b/src/jdk/internal/dynalink/support/Lookup.java
@@ -104,7 +104,7 @@ public class Lookup {
*
* @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to.
*/
- public Lookup(MethodHandles.Lookup lookup) {
+ public Lookup(final MethodHandles.Lookup lookup) {
this.lookup = lookup;
}
@@ -120,7 +120,7 @@ public class Lookup {
* @param m the method to unreflect
* @return the unreflected method handle.
*/
- public MethodHandle unreflect(Method m) {
+ public MethodHandle unreflect(final Method m) {
return unreflect(lookup, m);
}
@@ -132,10 +132,10 @@ public class Lookup {
* @param m the method to unreflect
* @return the unreflected method handle.
*/
- public static MethodHandle unreflect(MethodHandles.Lookup lookup, Method m) {
+ public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
try {
return lookup.unreflect(m);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m);
ee.initCause(e);
throw ee;
@@ -149,10 +149,10 @@ public class Lookup {
* @param f the field for which a getter is unreflected
* @return the unreflected field getter handle.
*/
- public MethodHandle unreflectGetter(Field f) {
+ public MethodHandle unreflectGetter(final Field f) {
try {
return lookup.unreflectGetter(f);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f);
ee.initCause(e);
throw ee;
@@ -171,15 +171,15 @@ public class Lookup {
* @throws IllegalAccessError if the field is inaccessible.
* @throws NoSuchFieldError if the field does not exist.
*/
- public MethodHandle findGetter(Class<?>refc, String name, Class<?> type) {
+ public MethodHandle findGetter(final Class<?>refc, final String name, final Class<?> type) {
try {
return lookup.findGetter(refc, name, type);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() +
"." + name + " of type " + type.getName());
ee.initCause(e);
throw ee;
- } catch(NoSuchFieldException e) {
+ } catch(final NoSuchFieldException e) {
final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() +
"." + name + " of type " + type.getName());
ee.initCause(e);
@@ -194,10 +194,10 @@ public class Lookup {
* @param f the field for which a setter is unreflected
* @return the unreflected field setter handle.
*/
- public MethodHandle unreflectSetter(Field f) {
+ public MethodHandle unreflectSetter(final Field f) {
try {
return lookup.unreflectSetter(f);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f);
ee.initCause(e);
throw ee;
@@ -211,7 +211,7 @@ public class Lookup {
* @param c the constructor to unreflect
* @return the unreflected constructor handle.
*/
- public MethodHandle unreflectConstructor(Constructor<?> c) {
+ public MethodHandle unreflectConstructor(final Constructor<?> c) {
return unreflectConstructor(lookup, c);
}
@@ -223,10 +223,10 @@ public class Lookup {
* @param c the constructor to unreflect
* @return the unreflected constructor handle.
*/
- public static MethodHandle unreflectConstructor(MethodHandles.Lookup lookup, Constructor<?> c) {
+ public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
try {
return lookup.unreflectConstructor(c);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c);
ee.initCause(e);
throw ee;
@@ -244,15 +244,15 @@ public class Lookup {
* @throws IllegalAccessError if the method is inaccessible.
* @throws NoSuchMethodError if the method does not exist.
*/
- public MethodHandle findSpecial(Class<?> declaringClass, String name, MethodType type) {
+ public MethodHandle findSpecial(final Class<?> declaringClass, final String name, final MethodType type) {
try {
return lookup.findSpecial(declaringClass, name, type, declaringClass);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
throw ee;
- } catch(NoSuchMethodException e) {
+ } catch(final NoSuchMethodException e) {
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
@@ -260,7 +260,7 @@ public class Lookup {
}
}
- private static String methodDescription(Class<?> declaringClass, String name, MethodType type) {
+ private static String methodDescription(final Class<?> declaringClass, final String name, final MethodType type) {
return declaringClass.getName() + "#" + name + type;
}
@@ -275,15 +275,15 @@ public class Lookup {
* @throws IllegalAccessError if the method is inaccessible.
* @throws NoSuchMethodError if the method does not exist.
*/
- public MethodHandle findStatic(Class<?> declaringClass, String name, MethodType type) {
+ public MethodHandle findStatic(final Class<?> declaringClass, final String name, final MethodType type) {
try {
return lookup.findStatic(declaringClass, name, type);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
throw ee;
- } catch(NoSuchMethodException e) {
+ } catch(final NoSuchMethodException e) {
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
@@ -302,15 +302,15 @@ public class Lookup {
* @throws IllegalAccessError if the method is inaccessible.
* @throws NoSuchMethodError if the method does not exist.
*/
- public MethodHandle findVirtual(Class<?> declaringClass, String name, MethodType type) {
+ public MethodHandle findVirtual(final Class<?> declaringClass, final String name, final MethodType type) {
try {
return lookup.findVirtual(declaringClass, name, type);
- } catch(IllegalAccessException e) {
+ } catch(final IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
throw ee;
- } catch(NoSuchMethodException e) {
+ } catch(final NoSuchMethodException e) {
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription(
declaringClass, name, type));
ee.initCause(e);
@@ -327,7 +327,7 @@ public class Lookup {
* @param ptypes the parameter types of the method
* @return the method handle for the method
*/
- public static MethodHandle findOwnSpecial(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
+ public static MethodHandle findOwnSpecial(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes);
}
@@ -341,7 +341,7 @@ public class Lookup {
* @param ptypes the parameter types of the method
* @return the method handle for the method
*/
- public MethodHandle findOwnSpecial(String name, Class<?> rtype, Class<?>... ptypes) {
+ public MethodHandle findOwnSpecial(final String name, final Class<?> rtype, final Class<?>... ptypes) {
return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
}
@@ -355,7 +355,7 @@ public class Lookup {
* @param ptypes the parameter types of the method
* @return the method handle for the method
*/
- public static MethodHandle findOwnStatic(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
+ public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Lookup(lookup).findOwnStatic(name, rtype, ptypes);
}
@@ -368,7 +368,7 @@ public class Lookup {
* @param ptypes the parameter types of the method
* @return the method handle for the method
*/
- public MethodHandle findOwnStatic(String name, Class<?> rtype, Class<?>... ptypes) {
+ public MethodHandle findOwnStatic(final String name, final Class<?> rtype, final Class<?>... ptypes) {
return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
}
}
diff --git a/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java b/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
index bc5521bb..e04321e6 100644
--- a/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
+++ b/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
@@ -92,7 +92,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
* @author Attila Szegedi
*/
class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
- private Lookup lookup;
+ private final Lookup lookup;
/**
* Create a new call site descriptor from explicit information.
@@ -100,7 +100,7 @@ class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
* @param methodType the method type
* @param lookup the lookup
*/
- LookupCallSiteDescriptor(String[] tokenizedName, MethodType methodType, Lookup lookup) {
+ LookupCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType, final Lookup lookup) {
super(tokenizedName, methodType);
this.lookup = lookup;
}
@@ -111,7 +111,7 @@ class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
}
@Override
- public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+ public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return new LookupCallSiteDescriptor(getTokenizedName(), newMethodType, lookup);
}
}
diff --git a/src/jdk/internal/dynalink/support/NameCodec.java b/src/jdk/internal/dynalink/support/NameCodec.java
index 1c7cd29b..9a402a59 100644
--- a/src/jdk/internal/dynalink/support/NameCodec.java
+++ b/src/jdk/internal/dynalink/support/NameCodec.java
@@ -137,7 +137,7 @@ public class NameCodec {
* @param name the symbolic name to mangle
* @return the mangled form of the symbolic name.
*/
- public static String encode(String name) {
+ public static String encode(final String name) {
final int l = name.length();
if(l == 0) {
return EMPTY_NAME;
@@ -176,7 +176,7 @@ public class NameCodec {
* @param name the symbolic name to demangle
* @return the demangled form of the symbolic name.
*/
- public static String decode(String name) {
+ public static String decode(final String name) {
if(name.charAt(0) != ESCAPE_CHAR) {
return name;
}
@@ -184,11 +184,11 @@ public class NameCodec {
if(l == 2 && name.charAt(1) == EMPTY_CHAR) {
return "";
}
- StringBuilder b = new StringBuilder(name.length());
+ final StringBuilder b = new StringBuilder(name.length());
int lastEscape = -2;
int lastBackslash = -1;
for(;;) {
- int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
+ final int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
if(nextBackslash == -1 || nextBackslash == l - 1) {
break;
}
@@ -211,7 +211,7 @@ public class NameCodec {
return b.toString();
}
- private static void addEncoding(char from, char to) {
+ private static void addEncoding(final char from, final char to) {
ENCODING[from - MIN_ENCODING] = to;
DECODING[to - MIN_DECODING] = from;
}
diff --git a/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java b/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
index 71cbb1d2..817df52a 100644
--- a/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
+++ b/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
@@ -89,7 +89,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
private final String name;
- NamedDynCallSiteDescriptor(String op, String name, MethodType methodType) {
+ NamedDynCallSiteDescriptor(final String op, final String name, final MethodType methodType) {
super(op, methodType);
this.name = name;
}
@@ -100,7 +100,7 @@ class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
}
@Override
- public String getNameToken(int i) {
+ public String getNameToken(final int i) {
switch(i) {
case 0: return "dyn";
case 1: return getOp();
@@ -110,7 +110,7 @@ class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
}
@Override
- public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+ public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new NamedDynCallSiteDescriptor(getOp(), name,
newMethodType));
}
diff --git a/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java b/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
index 03309a7c..3f43621a 100644
--- a/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
+++ b/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
@@ -101,15 +101,17 @@ public class RuntimeContextLinkRequestImpl extends LinkRequestImpl {
* Creates a new link request.
*
* @param callSiteDescriptor the descriptor for the call site being linked
+ * @param callSiteToken the opaque token for the call site being linked.
* @param arguments the arguments for the invocation
+ * @param linkCount number of times callsite has been linked/relinked
* @param callSiteUnstable true if the call site being linked is considered unstable
* @param runtimeContextArgCount the number of the leading arguments on the stack that represent the language
* runtime specific context arguments.
* @throws IllegalArgumentException if runtimeContextArgCount is less than 1.
*/
- public RuntimeContextLinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable,
- Object[] arguments, int runtimeContextArgCount) {
- super(callSiteDescriptor, callSiteUnstable, arguments);
+ public RuntimeContextLinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken,
+ final int linkCount, final boolean callSiteUnstable, final Object[] arguments, final int runtimeContextArgCount) {
+ super(callSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, arguments);
if(runtimeContextArgCount < 1) {
throw new IllegalArgumentException("runtimeContextArgCount < 1");
}
@@ -121,14 +123,14 @@ public class RuntimeContextLinkRequestImpl extends LinkRequestImpl {
if(contextStrippedRequest == null) {
contextStrippedRequest =
new LinkRequestImpl(CallSiteDescriptorFactory.dropParameterTypes(getCallSiteDescriptor(), 1,
- runtimeContextArgCount + 1), isCallSiteUnstable(), getTruncatedArguments());
+ runtimeContextArgCount + 1), getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), getTruncatedArguments());
}
return contextStrippedRequest;
}
@Override
- public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments) {
- return new RuntimeContextLinkRequestImpl(callSiteDescriptor, isCallSiteUnstable(), arguments,
+ public LinkRequest replaceArguments(final CallSiteDescriptor callSiteDescriptor, final Object[] arguments) {
+ return new RuntimeContextLinkRequestImpl(callSiteDescriptor, getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), arguments,
runtimeContextArgCount);
}
diff --git a/src/jdk/internal/dynalink/support/TypeConverterFactory.java b/src/jdk/internal/dynalink/support/TypeConverterFactory.java
index 436acad7..736b787c 100644
--- a/src/jdk/internal/dynalink/support/TypeConverterFactory.java
+++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java
@@ -97,6 +97,7 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
/**
* A factory for type converters. This class is the main implementation behind the
@@ -109,18 +110,19 @@ public class TypeConverterFactory {
private final GuardingTypeConverterFactory[] factories;
private final ConversionComparator[] comparators;
+ private final MethodTypeConversionStrategy autoConversionStrategy;
private final ClassValue<ClassMap<MethodHandle>> converterMap = new ClassValue<ClassMap<MethodHandle>>() {
@Override
protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
@Override
- protected MethodHandle computeValue(Class<?> targetType) {
+ protected MethodHandle computeValue(final Class<?> targetType) {
try {
return createConverter(sourceType, targetType);
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw e;
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
}
@@ -133,7 +135,7 @@ public class TypeConverterFactory {
protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
@Override
- protected MethodHandle computeValue(Class<?> targetType) {
+ protected MethodHandle computeValue(final Class<?> targetType) {
if(!canAutoConvert(sourceType, targetType)) {
final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
if(converter != IDENTITY_CONVERSION) {
@@ -151,12 +153,12 @@ public class TypeConverterFactory {
protected ClassMap<Boolean> computeValue(final Class<?> sourceType) {
return new ClassMap<Boolean>(getClassLoader(sourceType)) {
@Override
- protected Boolean computeValue(Class<?> targetType) {
+ protected Boolean computeValue(final Class<?> targetType) {
try {
return getTypeConverterNull(sourceType, targetType) != null;
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw e;
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
}
@@ -177,11 +179,27 @@ public class TypeConverterFactory {
* Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances.
*
* @param factories the {@link GuardingTypeConverterFactory} instances to compose.
+ * @param autoConversionStrategy conversion strategy for automatic type conversions. After
+ * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom
+ * conversions to a method handle, it still needs to effect
+ * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that
+ * can usually be automatically applied as per
+ * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}.
+ * However, sometimes language runtimes will want to customize even those conversions for their own call
+ * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by
+ * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom
+ * automatic conversion strategy, that can deal with null values. Note that when the strategy's
+ * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)}
+ * is invoked, the custom language conversions will already have been applied to the method handle, so by
+ * design the difference between the handle's current method type and the desired final type will always
+ * only be ones that can be subjected to method invocation conversions. Can be null, in which case no
+ * custom strategy is employed.
*/
- public TypeConverterFactory(Iterable<? extends GuardingTypeConverterFactory> factories) {
+ public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories,
+ final MethodTypeConversionStrategy autoConversionStrategy) {
final List<GuardingTypeConverterFactory> l = new LinkedList<>();
final List<ConversionComparator> c = new LinkedList<>();
- for(GuardingTypeConverterFactory factory: factories) {
+ for(final GuardingTypeConverterFactory factory: factories) {
l.add(factory);
if(factory instanceof ConversionComparator) {
c.add((ConversionComparator)factory);
@@ -189,24 +207,28 @@ public class TypeConverterFactory {
}
this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]);
this.comparators = c.toArray(new ConversionComparator[c.size()]);
-
+ this.autoConversionStrategy = autoConversionStrategy;
}
/**
* Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by
* {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of
- * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
- * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
- * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
- * provided by {@link GuardingTypeConverterFactory} implementations.
+ * parameters. For all conversions that are not a JLS method invocation conversion it'll insert
+ * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
+ * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation
+ * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first
+ * if an automatic conversion strategy was specified in the
+ * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply
+ * {@link MethodHandle#asType(MethodType)} for any remaining conversions.
*
* @param handle target method handle
* @param fromType the types of source arguments
- * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
+ * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)},
+ * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
* {@link GuardingTypeConverterFactory} produced type converters as filters.
*/
- public MethodHandle asType(MethodHandle handle, final MethodType fromType) {
+ public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
MethodHandle newHandle = handle;
final MethodType toType = newHandle.type();
final int l = toType.parameterCount();
@@ -246,11 +268,15 @@ public class TypeConverterFactory {
}
}
- // Take care of automatic conversions
- return newHandle.asType(fromType);
+ // Give change to automatic conversion strategy, if one is present.
+ final MethodHandle autoConvertedHandle =
+ autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle;
+
+ // Do a final asType for any conversions that remain.
+ return autoConvertedHandle.asType(fromType);
}
- private static MethodHandle applyConverters(MethodHandle handle, int pos, List<MethodHandle> converters) {
+ private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List<MethodHandle> converters) {
if(converters.isEmpty()) {
return handle;
}
@@ -285,8 +311,8 @@ public class TypeConverterFactory {
* @return one of Comparison constants that establish which - if any - of the target types is preferable for the
* conversion.
*/
- public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
- for(ConversionComparator comparator: comparators) {
+ public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+ for(final ConversionComparator comparator: comparators) {
final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2);
if(result != Comparison.INDETERMINATE) {
return result;
@@ -313,20 +339,20 @@ public class TypeConverterFactory {
return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
}
- /*private*/ MethodHandle getCacheableTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
+ /*private*/ MethodHandle getCacheableTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
return converter == IDENTITY_CONVERSION ? null : converter;
}
- /*private*/ MethodHandle getTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
+ /*private*/ MethodHandle getTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
try {
return getCacheableTypeConverterNull(sourceType, targetType);
- } catch(NotCacheableConverter e) {
+ } catch(final NotCacheableConverter e) {
return e.converter;
}
}
- /*private*/ MethodHandle getCacheableTypeConverter(Class<?> sourceType, Class<?> targetType) {
+ /*private*/ MethodHandle getCacheableTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
return converterMap.get(sourceType).get(targetType);
}
@@ -339,15 +365,15 @@ public class TypeConverterFactory {
* @param targetType the type to convert to
* @return a method handle performing the conversion.
*/
- public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
+ public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
try {
return converterIdentityMap.get(sourceType).get(targetType);
- } catch(NotCacheableConverter e) {
+ } catch(final NotCacheableConverter e) {
return e.converter;
}
}
- /*private*/ MethodHandle createConverter(Class<?> sourceType, Class<?> targetType) throws Exception {
+ /*private*/ MethodHandle createConverter(final Class<?> sourceType, final Class<?> targetType) throws Exception {
final MethodType type = MethodType.methodType(targetType, sourceType);
final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
MethodHandle last = identity;
@@ -372,6 +398,7 @@ public class TypeConverterFactory {
/*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
+ @SuppressWarnings("serial")
private static class NotCacheableConverter extends RuntimeException {
final MethodHandle converter;
diff --git a/src/jdk/internal/dynalink/support/TypeUtilities.java b/src/jdk/internal/dynalink/support/TypeUtilities.java
index 57fea990..bf4771b2 100644
--- a/src/jdk/internal/dynalink/support/TypeUtilities.java
+++ b/src/jdk/internal/dynalink/support/TypeUtilities.java
@@ -106,38 +106,49 @@ public class TypeUtilities {
}
/**
- * Given two types represented by c1 and c2, returns a type that is their most specific common superclass or
- * superinterface.
+ * Given two types represented by c1 and c2, returns a type that is their most specific common supertype for
+ * purposes of lossless conversions.
*
* @param c1 one type
* @param c2 another type
- * @return their most common superclass or superinterface. If they have several unrelated superinterfaces as their
- * most specific common type, or the types themselves are completely unrelated interfaces, {@link java.lang.Object}
- * is returned.
+ * @return their most common superclass or superinterface for purposes of lossless conversions. If they have several
+ * unrelated superinterfaces as their most specific common type, or the types themselves are completely
+ * unrelated interfaces, {@link java.lang.Object} is returned.
*/
- public static Class<?> getMostSpecificCommonType(Class<?> c1, Class<?> c2) {
+ public static Class<?> getCommonLosslessConversionType(final Class<?> c1, final Class<?> c2) {
if(c1 == c2) {
return c1;
+ } else if(isConvertibleWithoutLoss(c2, c1)) {
+ return c1;
+ } else if(isConvertibleWithoutLoss(c1, c2)) {
+ return c2;
+ }
+ if(c1 == void.class) {
+ return c2;
+ } else if(c2 == void.class) {
+ return c1;
}
- Class<?> c3 = c2;
- if(c3.isPrimitive()) {
- if(c3 == Byte.TYPE)
- c3 = Byte.class;
- else if(c3 == Short.TYPE)
- c3 = Short.class;
- else if(c3 == Character.TYPE)
- c3 = Character.class;
- else if(c3 == Integer.TYPE)
- c3 = Integer.class;
- else if(c3 == Float.TYPE)
- c3 = Float.class;
- else if(c3 == Long.TYPE)
- c3 = Long.class;
- else if(c3 == Double.TYPE)
- c3 = Double.class;
- }
- Set<Class<?>> a1 = getAssignables(c1, c3);
- Set<Class<?>> a2 = getAssignables(c3, c1);
+ if(c1.isPrimitive() && c2.isPrimitive()) {
+ if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) {
+ // byte + char = int
+ return int.class;
+ } else if((c1 == short.class && c2 == char.class) || (c1 == char.class && c2 == short.class)) {
+ // short + char = int
+ return int.class;
+ } else if((c1 == int.class && c2 == float.class) || (c1 == float.class && c2 == int.class)) {
+ // int + float = double
+ return double.class;
+ }
+ }
+ // For all other cases. This will handle long + (float|double) = Number case as well as boolean + anything = Object case too.
+ return getMostSpecificCommonTypeUnequalNonprimitives(c1, c2);
+ }
+
+ private static Class<?> getMostSpecificCommonTypeUnequalNonprimitives(final Class<?> c1, final Class<?> c2) {
+ final Class<?> npc1 = c1.isPrimitive() ? getWrapperType(c1) : c1;
+ final Class<?> npc2 = c2.isPrimitive() ? getWrapperType(c2) : c2;
+ final Set<Class<?>> a1 = getAssignables(npc1, npc2);
+ final Set<Class<?>> a2 = getAssignables(npc2, npc1);
a1.retainAll(a2);
if(a1.isEmpty()) {
// Can happen when at least one of the arguments is an interface,
@@ -148,10 +159,10 @@ public class TypeUtilities {
// thank to interfaces. I.e., if you call this method for String.class
// and Number.class, you'll have Comparable, Serializable, and Object
// as maximal elements.
- List<Class<?>> max = new ArrayList<>();
- outer: for(Class<?> clazz: a1) {
- for(Iterator<Class<?>> maxiter = max.iterator(); maxiter.hasNext();) {
- Class<?> maxClazz = maxiter.next();
+ final List<Class<?>> max = new ArrayList<>();
+ outer: for(final Class<?> clazz: a1) {
+ for(final Iterator<Class<?>> maxiter = max.iterator(); maxiter.hasNext();) {
+ final Class<?> maxClazz = maxiter.next();
if(isSubtype(maxClazz, clazz)) {
// It can't be maximal, if there's already a more specific
// maximal than it.
@@ -168,26 +179,26 @@ public class TypeUtilities {
max.add(clazz);
}
if(max.size() > 1) {
- return OBJECT_CLASS;
+ return Object.class;
}
return max.get(0);
}
- private static Set<Class<?>> getAssignables(Class<?> c1, Class<?> c2) {
- Set<Class<?>> s = new HashSet<>();
+ private static Set<Class<?>> getAssignables(final Class<?> c1, final Class<?> c2) {
+ final Set<Class<?>> s = new HashSet<>();
collectAssignables(c1, c2, s);
return s;
}
- private static void collectAssignables(Class<?> c1, Class<?> c2, Set<Class<?>> s) {
+ private static void collectAssignables(final Class<?> c1, final Class<?> c2, final Set<Class<?>> s) {
if(c1.isAssignableFrom(c2)) {
s.add(c1);
}
- Class<?> sc = c1.getSuperclass();
+ final Class<?> sc = c1.getSuperclass();
if(sc != null) {
collectAssignables(sc, c2, s);
}
- Class<?>[] itf = c1.getInterfaces();
+ final Class<?>[] itf = c1.getInterfaces();
for(int i = 0; i < itf.length; ++i) {
collectAssignables(itf[i], c2, s);
}
@@ -210,17 +221,17 @@ public class TypeUtilities {
return Collections.unmodifiableMap(wrapperTypes);
}
- private static Map<String, Class<?>> createClassNameMapping(Collection<Class<?>> classes) {
+ private static Map<String, Class<?>> createClassNameMapping(final Collection<Class<?>> classes) {
final Map<String, Class<?>> map = new HashMap<>();
- for(Class<?> clazz: classes) {
+ for(final Class<?> clazz: classes) {
map.put(clazz.getName(), clazz);
}
return map;
}
- private static <K, V> Map<V, K> invertMap(Map<K, V> map) {
+ private static <K, V> Map<V, K> invertMap(final Map<K, V> map) {
final Map<V, K> inverted = new IdentityHashMap<>(map.size());
- for(Map.Entry<K, V> entry: map.entrySet()) {
+ for(final Map.Entry<K, V> entry: map.entrySet()) {
inverted.put(entry.getValue(), entry.getKey());
}
return Collections.unmodifiableMap(inverted);
@@ -232,30 +243,59 @@ public class TypeUtilities {
* {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening
* reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion.
*
- * @param callSiteType the parameter type at the call site
- * @param methodType the parameter type in the method declaration
- * @return true if callSiteType is method invocation convertible to the methodType.
+ * @param sourceType the type being converted from (call site type for parameter types, method type for return types)
+ * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types)
+ * @return true if source type is method invocation convertible to target type.
*/
- public static boolean isMethodInvocationConvertible(Class<?> callSiteType, Class<?> methodType) {
- if(methodType.isAssignableFrom(callSiteType)) {
+ public static boolean isMethodInvocationConvertible(final Class<?> sourceType, final Class<?> targetType) {
+ if(targetType.isAssignableFrom(sourceType)) {
return true;
}
- if(callSiteType.isPrimitive()) {
- if(methodType.isPrimitive()) {
- return isProperPrimitiveSubtype(callSiteType, methodType);
+ if(sourceType.isPrimitive()) {
+ if(targetType.isPrimitive()) {
+ return isProperPrimitiveSubtype(sourceType, targetType);
}
// Boxing + widening reference conversion
- return methodType.isAssignableFrom(WRAPPER_TYPES.get(callSiteType));
+ assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName();
+ return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType));
}
- if(methodType.isPrimitive()) {
- final Class<?> unboxedCallSiteType = PRIMITIVE_TYPES.get(callSiteType);
+ if(targetType.isPrimitive()) {
+ final Class<?> unboxedCallSiteType = PRIMITIVE_TYPES.get(sourceType);
return unboxedCallSiteType != null
- && (unboxedCallSiteType == methodType || isProperPrimitiveSubtype(unboxedCallSiteType, methodType));
+ && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType));
}
return false;
}
/**
+ * Determines whether a type can be converted to another without losing any
+ * precision.
+ *
+ * @param sourceType the source type
+ * @param targetType the target type
+ * @return true if lossless conversion is possible
+ */
+ public static boolean isConvertibleWithoutLoss(final Class<?> sourceType, final Class<?> targetType) {
+ if(targetType.isAssignableFrom(sourceType)) {
+ return true;
+ }
+ if(sourceType.isPrimitive()) {
+ if(sourceType == void.class) {
+ return false; // Void can't be losslessly represented by any type
+ }
+ if(targetType.isPrimitive()) {
+ return isProperPrimitiveLosslessSubtype(sourceType, targetType);
+ }
+ // Boxing + widening reference conversion
+ assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName();
+ return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType));
+ }
+ // Can't convert from any non-primitive type to any primitive type without data loss because of null.
+ // Also, can't convert non-assignable reference types.
+ return false;
+ }
+
+ /**
* Determines whether one type can be potentially converted to another type at runtime. Allows a conversion between
* any subtype and supertype in either direction, and also allows a conversion between any two primitive types, as
* well as between any primitive type and any reference type that can hold a boxed primitive.
@@ -264,9 +304,9 @@ public class TypeUtilities {
* @param methodType the parameter type in the method declaration
* @return true if callSiteType is potentially convertible to the methodType.
*/
- public static boolean isPotentiallyConvertible(Class<?> callSiteType, Class<?> methodType) {
+ public static boolean isPotentiallyConvertible(final Class<?> callSiteType, final Class<?> methodType) {
// Widening or narrowing reference conversion
- if(methodType.isAssignableFrom(callSiteType) || callSiteType.isAssignableFrom(methodType)) {
+ if(areAssignable(callSiteType, methodType)) {
return true;
}
if(callSiteType.isPrimitive()) {
@@ -287,6 +327,16 @@ public class TypeUtilities {
}
/**
+ * Returns true if either of the types is assignable from the other.
+ * @param c1 one of the types
+ * @param c2 another one of the types
+ * @return true if either c1 is assignable from c2 or c2 is assignable from c1.
+ */
+ public static boolean areAssignable(final Class<?> c1, final Class<?> c2) {
+ return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1);
+ }
+
+ /**
* Determines whether one type is a subtype of another type, as per JLS 4.10 "Subtyping". Note: this is not strict
* or proper subtype, therefore true is also returned for identical types; to be completely precise, it allows
* identity conversion (JLS 5.1.1), widening primitive conversion (JLS 5.1.2) and widening reference conversion (JLS
@@ -297,7 +347,7 @@ public class TypeUtilities {
* @return true if subType can be converted by identity conversion, widening primitive conversion, or widening
* reference conversion to superType.
*/
- public static boolean isSubtype(Class<?> subType, Class<?> superType) {
+ public static boolean isSubtype(final Class<?> subType, final Class<?> superType) {
// Covers both JLS 4.10.2 "Subtyping among Class and Interface Types"
// and JLS 4.10.3 "Subtyping among Array Types", as well as primitive
// type identity.
@@ -328,7 +378,7 @@ public class TypeUtilities {
* @param superType the supposed supertype
* @return true if subType is a proper (not identical to) primitive subtype of the superType
*/
- private static boolean isProperPrimitiveSubtype(Class<?> subType, Class<?> superType) {
+ private static boolean isProperPrimitiveSubtype(final Class<?> subType, final Class<?> superType) {
if(superType == boolean.class || subType == boolean.class) {
return false;
}
@@ -353,6 +403,37 @@ public class TypeUtilities {
return false;
}
+ /**
+ * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to
+ * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and
+ * anything else (similar to boolean) as char is not meant to be an arithmetic type.
+ * @param subType the supposed subtype
+ * @param superType the supposed supertype
+ * @return true if subType is a proper (not identical to) primitive subtype of the superType that can be represented
+ * by the supertype without no precision loss.
+ */
+ private static boolean isProperPrimitiveLosslessSubtype(final Class<?> subType, final Class<?> superType) {
+ if(superType == boolean.class || subType == boolean.class) {
+ return false;
+ }
+ if(superType == char.class || subType == char.class) {
+ return false;
+ }
+ if(subType == byte.class) {
+ return true;
+ }
+ if(subType == short.class) {
+ return superType != byte.class;
+ }
+ if(subType == int.class) {
+ return superType == long.class || superType == double.class;
+ }
+ if(subType == float.class) {
+ return superType == double.class;
+ }
+ return false;
+ }
+
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPES = createWrapperToPrimitiveTypes();
private static Map<Class<?>, Class<?>> createWrapperToPrimitiveTypes() {
@@ -384,13 +465,13 @@ public class TypeUtilities {
return classes.keySet();
}
- private static void addClassHierarchy(Map<Class<?>, Class<?>> map, Class<?> clazz) {
+ private static void addClassHierarchy(final Map<Class<?>, Class<?>> map, final Class<?> clazz) {
if(clazz == null) {
return;
}
map.put(clazz, clazz);
addClassHierarchy(map, clazz.getSuperclass());
- for(Class<?> itf: clazz.getInterfaces()) {
+ for(final Class<?> itf: clazz.getInterfaces()) {
addClassHierarchy(map, itf);
}
}
@@ -402,7 +483,7 @@ public class TypeUtilities {
* @return true if the class can be assigned from any boxed primitive. Basically, it is true if the class is any
* primitive wrapper class, or a superclass or superinterface of any primitive wrapper class.
*/
- private static boolean isAssignableFromBoxedPrimitive(Class<?> clazz) {
+ private static boolean isAssignableFromBoxedPrimitive(final Class<?> clazz) {
return PRIMITIVE_WRAPPER_TYPES.contains(clazz);
}
@@ -413,7 +494,7 @@ public class TypeUtilities {
* @return the class representing the primitive type, or null if the name does not correspond to a primitive type
* or is "void".
*/
- public static Class<?> getPrimitiveTypeByName(String name) {
+ public static Class<?> getPrimitiveTypeByName(final String name) {
return PRIMITIVE_TYPES_BY_NAME.get(name);
}
@@ -424,7 +505,7 @@ public class TypeUtilities {
* @param wrapperType the class object representing a wrapper for a primitive type
* @return the class object representing the primitive type, or null if the passed class is not a primitive wrapper.
*/
- public static Class<?> getPrimitiveType(Class<?> wrapperType) {
+ public static Class<?> getPrimitiveType(final Class<?> wrapperType) {
return WRAPPER_TO_PRIMITIVE_TYPES.get(wrapperType);
}
@@ -436,7 +517,16 @@ public class TypeUtilities {
* @param primitiveType the class object representing a primitive type
* @return the class object representing the wrapper type, or null if the passed class is not a primitive.
*/
- public static Class<?> getWrapperType(Class<?> primitiveType) {
+ public static Class<?> getWrapperType(final Class<?> primitiveType) {
return WRAPPER_TYPES.get(primitiveType);
}
+
+ /**
+ * Returns true if the passed type is a wrapper for a primitive type.
+ * @param type the examined type
+ * @return true if the passed type is a wrapper for a primitive type.
+ */
+ public static boolean isWrapperType(final Class<?> type) {
+ return PRIMITIVE_TYPES.containsKey(type);
+ }
}
diff --git a/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java b/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
index da8c0096..89a0677e 100644
--- a/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
+++ b/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
@@ -90,7 +90,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor {
private final MethodType methodType;
private final String op;
- UnnamedDynCallSiteDescriptor(String op, MethodType methodType) {
+ UnnamedDynCallSiteDescriptor(final String op, final MethodType methodType) {
this.op = op;
this.methodType = methodType;
}
@@ -105,7 +105,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor {
}
@Override
- public String getNameToken(int i) {
+ public String getNameToken(final int i) {
switch(i) {
case 0: return "dyn";
case 1: return op;
@@ -119,7 +119,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor {
}
@Override
- public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+ public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new UnnamedDynCallSiteDescriptor(op,
newMethodType));
}
diff --git a/src/jdk/internal/dynalink/support/messages.properties b/src/jdk/internal/dynalink/support/messages.properties
index 88d59908..ed26299e 100644
--- a/src/jdk/internal/dynalink/support/messages.properties
+++ b/src/jdk/internal/dynalink/support/messages.properties
@@ -83,4 +83,4 @@ isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type
isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false
isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true
-isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false \ No newline at end of file
+isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false
diff --git a/src/jdk/nashorn/api/scripting/ClassFilter.java b/src/jdk/nashorn/api/scripting/ClassFilter.java
new file mode 100644
index 00000000..ddf1bc33
--- /dev/null
+++ b/src/jdk/nashorn/api/scripting/ClassFilter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.scripting;
+
+/**
+ * Class filter (optional) to be used by nashorn script engine.
+ * jsr-223 program embedding nashorn script can set ClassFilter instance
+ * to be used when an engine instance is created.
+ */
+public interface ClassFilter {
+ /**
+ * Should the Java class of the specified name be exposed to scripts?
+ * @param className is the fully qualified name of the java class being
+ * checked. This will not be null. Only non-array class names will be
+ * passed.
+ * @return true if the java class can be exposed to scripts false otherwise
+ */
+ public boolean exposeToScripts(String className);
+}
diff --git a/src/jdk/nashorn/api/scripting/Formatter.java b/src/jdk/nashorn/api/scripting/Formatter.java
index a14a83e4..544e70ce 100644
--- a/src/jdk/nashorn/api/scripting/Formatter.java
+++ b/src/jdk/nashorn/api/scripting/Formatter.java
@@ -65,8 +65,8 @@ final class Formatter {
while (m.find()) {
int index = index(m.group(1));
- boolean previous = isPreviousArgument(m.group(2));
- char conversion = m.group(6).charAt(0);
+ final boolean previous = isPreviousArgument(m.group(2));
+ final char conversion = m.group(6).charAt(0);
// skip over some formats
if (index < 0 || previous
@@ -85,7 +85,7 @@ final class Formatter {
}
// current argument
- Object arg = args[index - 1];
+ final Object arg = args[index - 1];
// for date we convert double to long
if (m.group(5) != null) {
diff --git a/src/jdk/nashorn/api/scripting/JSObject.java b/src/jdk/nashorn/api/scripting/JSObject.java
index bd6e820b..8d818642 100644
--- a/src/jdk/nashorn/api/scripting/JSObject.java
+++ b/src/jdk/nashorn/api/scripting/JSObject.java
@@ -26,7 +26,6 @@
package jdk.nashorn.api.scripting;
import java.util.Collection;
-import java.util.Collections;
import java.util.Set;
/**
diff --git a/src/jdk/nashorn/api/scripting/NashornException.java b/src/jdk/nashorn/api/scripting/NashornException.java
index a5f8c24a..098f8508 100644
--- a/src/jdk/nashorn/api/scripting/NashornException.java
+++ b/src/jdk/nashorn/api/scripting/NashornException.java
@@ -53,9 +53,6 @@ public abstract class NashornException extends RuntimeException {
// underlying ECMA error object - lazily initialized
private Object ecmaError;
- /** script source name used for "engine.js" */
- public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
-
/**
* Constructor
*
@@ -182,7 +179,7 @@ public abstract class NashornException extends RuntimeException {
if (ECMAErrors.isScriptFrame(st)) {
final String className = "<" + st.getFileName() + ">";
String methodName = st.getMethodName();
- if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
+ if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) {
methodName = "<program>";
}
@@ -224,10 +221,22 @@ public abstract class NashornException extends RuntimeException {
return buf.toString();
}
+ /**
+ * Get the thrown object. Subclass responsibility
+ * @return thrown object
+ */
protected Object getThrown() {
return null;
}
+ /**
+ * Initialization function for ECMA errors. Stores the error
+ * in the ecmaError field of this class. It is only initialized
+ * once, and then reused
+ *
+ * @param global the global
+ * @return initialized exception
+ */
protected NashornException initEcmaError(final ScriptObject global) {
if (ecmaError != null) {
return this; // initialized already!
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 7ebe5c91..2f000954 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -25,8 +25,6 @@
package jdk.nashorn.api.scripting;
-import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.IOException;
@@ -34,13 +32,10 @@ import java.io.Reader;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.net.URL;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.Locale;
@@ -58,7 +53,6 @@ import javax.script.SimpleBindings;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
-import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -98,12 +92,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
// This is the initial default Nashorn global object.
// This is used as "shared" global if above option is true.
private final Global global;
- // initialized bit late to be made 'final'.
- // Property object for "context" property of global object.
- private volatile Property contextProperty;
-
- // default options passed to Nashorn Options object
- private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
// Nashorn script engine error message management
private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";
@@ -122,36 +110,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
- // load engine.js
- @SuppressWarnings("resource")
- private static Source loadEngineJSSource() {
- final String script = "resources/engine.js";
- try {
- return AccessController.doPrivileged(
- new PrivilegedExceptionAction<Source>() {
- @Override
- public Source run() throws IOException {
- final URL url = NashornScriptEngine.class.getResource(script);
- return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
- }
- }
- );
- } catch (final PrivilegedActionException e) {
- if (Context.DEBUG) {
- e.printStackTrace();
- }
- throw new RuntimeException(e);
- }
- }
-
- // Source object for engine.js
- private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
-
- NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
- this(factory, DEFAULT_OPTIONS, appLoader);
- }
-
- NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader) {
+ NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
+ assert args != null : "null argument array";
this.factory = factory;
final Options options = new Options("nashorn");
options.process(args);
@@ -163,7 +123,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
@Override
public Context run() {
try {
- return new Context(options, errMgr, appLoader);
+ return new Context(options, errMgr, appLoader, classFilter);
} catch (final RuntimeException e) {
if (Context.DEBUG) {
e.printStackTrace();
@@ -249,39 +209,12 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return getInterfaceInner(thiz, clazz);
}
- // These are called from the "engine.js" script
-
- /**
- * This hook is used to search js global variables exposed from Java code.
- *
- * @param self 'this' passed from the script
- * @param ctxt current ScriptContext in which name is searched
- * @param name name of the variable searched
- * @return the value of the named variable
- */
- public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
- if (ctxt != null) {
- final int scope = ctxt.getAttributesScope(name);
- final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
- if (scope != -1) {
- return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
- }
-
- if (self == UNDEFINED) {
- // scope access and so throw ReferenceError
- throw referenceError(ctxtGlobal, "not.defined", name);
- }
- }
-
- return UNDEFINED;
- }
-
// Implementation only below this point
private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
try {
return sourceFor(getScriptName(ctxt), reader);
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new ScriptException(e);
}
}
@@ -296,6 +229,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
+ assert !(thiz instanceof ScriptObject) : "raw ScriptObject not expected here";
+
if (clazz == null || !clazz.isInterface()) {
throw new IllegalArgumentException(getMessage("interface.class.expected"));
}
@@ -321,17 +256,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
if (! isOfContext(realGlobal, nashornContext)) {
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
- } else if (thiz instanceof ScriptObject) {
- // called from script code.
- realSelf = (ScriptObject)thiz;
- realGlobal = Context.getGlobal();
- if (realGlobal == null) {
- throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
- }
-
- if (! isOfContext(realGlobal, nashornContext)) {
- throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
- }
}
if (realSelf == null) {
@@ -380,7 +304,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
// Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
- Object scope = bindings.get(NASHORN_GLOBAL);
+ final Object scope = bindings.get(NASHORN_GLOBAL);
if (scope instanceof ScriptObjectMirror) {
final Global glob = globalFromMirror((ScriptObjectMirror)scope);
if (glob != null) {
@@ -397,7 +321,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
// Retrieve nashorn Global object from a given ScriptObjectMirror
private Global globalFromMirror(final ScriptObjectMirror mirror) {
- ScriptObject sobj = mirror.getScriptObject();
+ final ScriptObject sobj = mirror.getScriptObject();
if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) {
return (Global)sobj;
}
@@ -427,49 +351,15 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}, CREATE_GLOBAL_ACC_CTXT);
- nashornContext.initGlobal(newGlobal);
-
- final int NON_ENUMERABLE_CONSTANT = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE;
- // current ScriptContext exposed as "context"
- // "context" is non-writable from script - but script engine still
- // needs to set it and so save the context Property object
- contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, ctxt);
- // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
- // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
- // in the Global of a Context we just created - both the Context and the Global were just created and can not be
- // seen from another thread outside of this constructor.
- newGlobal.addOwnProperty("engine", NON_ENUMERABLE_CONSTANT, this);
- // global script arguments with undefined value
- newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
- // file name default is null
- newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
- // evaluate engine.js initialization script this new global object
- try {
- evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
- } catch (final ScriptException exp) {
- throw new RuntimeException(exp);
- }
- return newGlobal;
- }
+ nashornContext.initGlobal(newGlobal, this);
+ newGlobal.setScriptContext(ctxt);
- // scripts should see "context" and "engine" as variables in the given global object
- private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
- // set "context" global variable via contextProperty - because this
- // property is non-writable
- contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
- Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
- if (args == null || args == UNDEFINED) {
- args = ScriptRuntime.EMPTY_ARRAY;
- }
- // if no arguments passed, expose it
- if (! (args instanceof ScriptObject)) {
- args = ctxtGlobal.wrapAsObject(args);
- ctxtGlobal.set("arguments", args, false);
- }
+ return newGlobal;
}
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
name.getClass(); // null check
+ assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";
Global invokeGlobal = null;
ScriptObjectMirror selfMirror = null;
@@ -479,20 +369,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
invokeGlobal = selfMirror.getHomeGlobal();
- } else if (selfObject instanceof ScriptObject) {
- // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
- // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
- final Global oldGlobal = Context.getGlobal();
- invokeGlobal = oldGlobal;
- if (oldGlobal == null) {
- throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
- }
-
- if (! isOfContext(oldGlobal, nashornContext)) {
- throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
- }
-
- selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
} else if (selfObject == null) {
// selfObject is null => global function call
final Global ctxtGlobal = getNashornGlobalFrom(context);
@@ -525,7 +401,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
}
- private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
@@ -534,11 +410,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
-
- // set ScriptContext variables if ctxt is non-null
- if (ctxt != null) {
- setContextVariables(ctxtGlobal, ctxt);
- }
+ ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
throwAsScriptException(e, ctxtGlobal);
@@ -550,7 +422,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
- private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
}
@@ -561,10 +433,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
Context.setGlobal(ctxtGlobal);
}
- // set ScriptContext variables if ctxt is non-null
- if (ctxt != null) {
- setContextVariables(ctxtGlobal, ctxt);
- }
+ ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
throwAsScriptException(e, ctxtGlobal);
@@ -671,7 +540,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
continue;
}
- Object obj = sobj.get(method.getName());
+ final Object obj = sobj.get(method.getName());
if (! (obj instanceof ScriptFunction)) {
return false;
}
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
index beb0c2a0..4ddcf947 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
@@ -135,10 +135,13 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
return sb.toString();
}
+ // default options passed to Nashorn script engine
+ private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
+
@Override
public ScriptEngine getScriptEngine() {
try {
- return new NashornScriptEngine(this, getAppClassLoader());
+ return new NashornScriptEngine(this, DEFAULT_OPTIONS, getAppClassLoader(), null);
} catch (final RuntimeException e) {
if (Context.DEBUG) {
e.printStackTrace();
@@ -152,10 +155,27 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
*
* @param appLoader class loader to be used as script "app" class loader.
* @return newly created script engine.
+ * @throws SecurityException
+ * if the security manager's {@code checkPermission}
+ * denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final ClassLoader appLoader) {
- checkConfigPermission();
- return new NashornScriptEngine(this, appLoader);
+ return newEngine(DEFAULT_OPTIONS, appLoader, null);
+ }
+
+ /**
+ * Create a new Script engine initialized by given class filter.
+ *
+ * @param classFilter class filter to use.
+ * @return newly created script engine.
+ * @throws NullPointerException if {@code classFilter} is {@code null}
+ * @throws SecurityException
+ * if the security manager's {@code checkPermission}
+ * denies {@code RuntimePermission("nashorn.setConfig")}
+ */
+ public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
+ classFilter.getClass(); // null check
+ return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter);
}
/**
@@ -163,10 +183,14 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
*
* @param args arguments array passed to script engine.
* @return newly created script engine.
+ * @throws NullPointerException if {@code args} is {@code null}
+ * @throws SecurityException
+ * if the security manager's {@code checkPermission}
+ * denies {@code RuntimePermission("nashorn.setConfig")}
*/
- public ScriptEngine getScriptEngine(final String[] args) {
- checkConfigPermission();
- return new NashornScriptEngine(this, args, getAppClassLoader());
+ public ScriptEngine getScriptEngine(final String... args) {
+ args.getClass(); // null check
+ return newEngine(args, getAppClassLoader(), null);
}
/**
@@ -175,10 +199,44 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
* @param args arguments array passed to script engine.
* @param appLoader class loader to be used as script "app" class loader.
* @return newly created script engine.
+ * @throws NullPointerException if {@code args} is {@code null}
+ * @throws SecurityException
+ * if the security manager's {@code checkPermission}
+ * denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
+ args.getClass(); // null check
+ return newEngine(args, appLoader, null);
+ }
+
+ /**
+ * Create a new Script engine initialized by given arguments.
+ *
+ * @param args arguments array passed to script engine.
+ * @param appLoader class loader to be used as script "app" class loader.
+ * @param classFilter class filter to use.
+ * @return newly created script engine.
+ * @throws NullPointerException if {@code args} or {@code classFilter} is {@code null}
+ * @throws SecurityException
+ * if the security manager's {@code checkPermission}
+ * denies {@code RuntimePermission("nashorn.setConfig")}
+ */
+ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
+ args.getClass(); // null check
+ classFilter.getClass(); // null check
+ return newEngine(args, appLoader, classFilter);
+ }
+
+ private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
checkConfigPermission();
- return new NashornScriptEngine(this, args, appLoader);
+ try {
+ return new NashornScriptEngine(this, args, appLoader, classFilter);
+ } catch (final RuntimeException e) {
+ if (Context.DEBUG) {
+ e.printStackTrace();
+ }
+ throw e;
+ }
}
// -- Internals only below this point
@@ -220,7 +278,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory {
// Revisit: script engine implementation needs the capability to
// find the class loader of the context in which the script engine
// is running so that classes will be found and loaded properly
- ClassLoader ccl = Thread.currentThread().getContextClassLoader();
+ final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
return (ccl == null)? NashornScriptEngineFactory.class.getClassLoader() : ccl;
}
}
diff --git a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index b8035d2e..e28da041 100644
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -43,13 +43,14 @@ import java.util.Set;
import java.util.concurrent.Callable;
import javax.script.Bindings;
import jdk.nashorn.internal.objects.Global;
-import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
* Mirror object that wraps a given Nashorn Script object.
@@ -164,11 +165,17 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
return Context.getContext();
}
}, GET_CONTEXT_ACC_CTXT);
- return wrap(context.eval(global, s, null, null, false), global);
+ return wrap(context.eval(global, s, sobj, null, false), global);
}
});
}
+ /**
+ * Call member function
+ * @param functionName function name
+ * @param args arguments
+ * @return return value of function
+ */
public Object callMember(final String functionName, final Object... args) {
functionName.getClass(); // null check
final Global oldGlobal = Context.getGlobal();
@@ -255,7 +262,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
public void setSlot(final int index, final Object value) {
inGlobal(new Callable<Void>() {
@Override public Void call() {
- sobj.set(index, unwrap(value, global), strict);
+ sobj.set(index, unwrap(value, global), getCallSiteFlags());
return null;
}
});
@@ -419,7 +426,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
final Object value = entry.getValue();
final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
- sobj.set(entry.getKey(), unwrap(modValue, global), strict);
+ sobj.set(entry.getKey(), unwrap(modValue, global), getCallSiteFlags());
}
return null;
}
@@ -709,6 +716,23 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
return newArgs;
}
+ /**
+ * Are the given objects mirrors to same underlying object?
+ *
+ * @param obj1 first object
+ * @param obj2 second object
+ * @return true if obj1 and obj2 are identical script objects or mirrors of it.
+ */
+ public static boolean identical(final Object obj1, final Object obj2) {
+ final Object o1 = (obj1 instanceof ScriptObjectMirror)?
+ ((ScriptObjectMirror)obj1).sobj : obj1;
+
+ final Object o2 = (obj2 instanceof ScriptObjectMirror)?
+ ((ScriptObjectMirror)obj2).sobj : obj2;
+
+ return o1 == o2;
+ }
+
// package-privates below this.
ScriptObjectMirror(final ScriptObject sobj, final Global global) {
@@ -729,10 +753,14 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
return global;
}
- static Object translateUndefined(Object obj) {
+ static Object translateUndefined(final Object obj) {
return (obj == ScriptRuntime.UNDEFINED)? null : obj;
}
+ private int getCallSiteFlags() {
+ return strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+ }
+
// internals only below this.
private <V> V inGlobal(final Callable<V> callable) {
final Global oldGlobal = Context.getGlobal();
diff --git a/src/jdk/nashorn/api/scripting/ScriptUtils.java b/src/jdk/nashorn/api/scripting/ScriptUtils.java
index 29d03db4..b6c4c97e 100644
--- a/src/jdk/nashorn/api/scripting/ScriptUtils.java
+++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java
@@ -25,14 +25,16 @@
package jdk.nashorn.api.scripting;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.LinkerServices;
-import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
* Utilities that are to be called from script code.
@@ -69,12 +71,12 @@ public final class ScriptUtils {
* Create a wrapper function that calls {@code func} synchronized on {@code sync} or, if that is undefined,
* {@code self}. Used to implement "sync" function in resources/mozilla_compat.js.
*
- * @param func the function to invoke
+ * @param func the function to wrap
* @param sync the object to synchronize on
* @return a synchronizing wrapper function
*/
public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
- return func.makeSynchronizedFunction(sync);
+ return func.makeSynchronizedFunction(unwrap(sync));
}
/**
@@ -83,12 +85,8 @@ public final class ScriptUtils {
* @param obj object to be wrapped
* @return wrapped object
*/
- public static Object wrap(final Object obj) {
- if (obj instanceof ScriptObject) {
- return ScriptObjectMirror.wrap(obj, Context.getGlobal());
- }
-
- return obj;
+ public static ScriptObjectMirror wrap(final ScriptObject obj) {
+ return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal());
}
/**
@@ -155,14 +153,15 @@ public final class ScriptUtils {
}
final LinkerServices linker = Bootstrap.getLinkerServices();
- final MethodHandle converter = linker.getTypeConverter(obj.getClass(), clazz);
+ final Object objToConvert = unwrap(obj);
+ final MethodHandle converter = linker.getTypeConverter(objToConvert.getClass(), clazz);
if (converter == null) {
// no supported conversion!
throw new UnsupportedOperationException("conversion not supported");
}
try {
- return converter.invoke(obj);
+ return converter.invoke(objToConvert);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
diff --git a/src/jdk/nashorn/api/scripting/URLReader.java b/src/jdk/nashorn/api/scripting/URLReader.java
index 13f69843..53efeee7 100644
--- a/src/jdk/nashorn/api/scripting/URLReader.java
+++ b/src/jdk/nashorn/api/scripting/URLReader.java
@@ -81,7 +81,7 @@ public final class URLReader extends Reader {
}
@Override
- public int read(char cbuf[], int off, int len) throws IOException {
+ public int read(final char cbuf[], final int off, final int len) throws IOException {
return getReader().read(cbuf, off, len);
}
diff --git a/src/jdk/nashorn/api/scripting/resources/engine.js b/src/jdk/nashorn/api/scripting/resources/engine.js
deleted file mode 100644
index b9034292..00000000
--- a/src/jdk/nashorn/api/scripting/resources/engine.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * This script file is executed by script engine at the construction
- * of the every new Global object. The functions here assume global variables
- * "context" of type javax.script.ScriptContext and "engine" of the type
- * jdk.nashorn.api.scripting.NashornScriptEngine.
- **/
-
-Object.defineProperty(this, "__noSuchProperty__", {
- configurable: true,
- enumerable: false,
- writable: true,
- value: function (name) {
- 'use strict';
- return engine.__noSuchProperty__(this, context, name);
- }
-});
-
-function print() {
- var writer = context != null? context.writer : engine.context.writer;
- if (! (writer instanceof java.io.PrintWriter)) {
- writer = new java.io.PrintWriter(writer);
- }
-
- var buf = new java.lang.StringBuilder();
- for (var i = 0; i < arguments.length; i++) {
- if (i != 0) {
- buf.append(' ');
- }
- buf.append(String(arguments[i]));
- }
- writer.println(buf.toString());
-}
-
-/**
- * This is C-like printf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "printf", {
- configurable: true,
- enumerable: false,
- writable: true,
- value: function (format, args/*, more args*/) {
- print(sprintf.apply(this, arguments));
- }
-});
-
-/**
- * This is C-like sprintf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "sprintf", {
- configurable: true,
- enumerable: false,
- writable: true,
- value: function (format, args/*, more args*/) {
- var len = arguments.length - 1;
- var array = [];
-
- if (len < 0) {
- return "";
- }
-
- for (var i = 0; i < len; i++) {
- if (arguments[i+1] instanceof Date) {
- array[i] = arguments[i+1].getTime();
- } else {
- array[i] = arguments[i+1];
- }
- }
-
- array = Java.to(array);
- return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
- }
-});
diff --git a/src/jdk/nashorn/internal/AssertsEnabled.java b/src/jdk/nashorn/internal/AssertsEnabled.java
new file mode 100644
index 00000000..73d9dfdc
--- /dev/null
+++ b/src/jdk/nashorn/internal/AssertsEnabled.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal;
+
+/**
+ * Class that exposes the current state of asserts.
+ */
+@SuppressWarnings("all")
+public final class AssertsEnabled {
+ private static boolean assertsEnabled = false;
+ static {
+ assert assertsEnabled = true; // Intentional side effect
+ }
+
+ /**
+ * Returns true if asserts are enabled
+ * @return true if asserts are enabled
+ */
+ public static boolean assertsEnabled() {
+ return assertsEnabled;
+ }
+}
diff --git a/src/jdk/nashorn/internal/IntDeque.java b/src/jdk/nashorn/internal/IntDeque.java
new file mode 100644
index 00000000..477afcf9
--- /dev/null
+++ b/src/jdk/nashorn/internal/IntDeque.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal;
+
+/**
+ * Small helper class for fast int deques
+ */
+public class IntDeque {
+ private int[] deque = new int[16];
+ private int nextFree = 0;
+
+ /**
+ * Push an int value
+ * @param value value
+ */
+ public void push(final int value) {
+ if (nextFree == deque.length) {
+ final int[] newDeque = new int[nextFree * 2];
+ System.arraycopy(deque, 0, newDeque, 0, nextFree);
+ deque = newDeque;
+ }
+ deque[nextFree++] = value;
+ }
+
+ /**
+ * Pop an int value
+ * @return value
+ */
+ public int pop() {
+ return deque[--nextFree];
+ }
+
+ /**
+ * Peek
+ * @return top value
+ */
+ public int peek() {
+ return deque[nextFree - 1];
+ }
+
+ /**
+ * Get the value of the top element and increment it.
+ * @return top value
+ */
+ public int getAndIncrement() {
+ return deque[nextFree - 1]++;
+ }
+
+ /**
+ * Decrement the value of the top element and return it.
+ * @return decremented top value
+ */
+ public int decrementAndGet() {
+ return --deque[nextFree - 1];
+ }
+
+ /**
+ * Check if deque is empty
+ * @return true if empty
+ */
+ public boolean isEmpty() {
+ return nextFree == 0;
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
new file mode 100644
index 00000000..62e58f46
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
+
+import java.lang.invoke.MethodType;
+import java.net.URL;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * An optimization that attempts to turn applies into calls. This pattern
+ * is very common for fake class instance creation, and apply
+ * introduces expensive args collection and boxing
+ *
+ * <pre>
+ * var Class = {
+ * create: function() {
+ * return function() { //vararg
+ * this.initialize.apply(this, arguments);
+ * }
+ * }
+ * };
+ *
+ * Color = Class.create();
+ *
+ * Color.prototype = {
+ * red: 0, green: 0, blue: 0,
+ * initialize: function(r,g,b) {
+ * this.red = r;
+ * this.green = g;
+ * this.blue = b;
+ * }
+ * }
+ *
+ * new Color(17, 47, 11);
+ * </pre>
+ */
+
+@Logger(name="apply2call")
+public final class ApplySpecialization extends NodeVisitor<LexicalContext> implements Loggable {
+
+ private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
+
+ private final DebugLogger log;
+
+ private final Compiler compiler;
+
+ private final Set<Integer> changed = new HashSet<>();
+
+ private final Deque<List<IdentNode>> explodedArguments = new ArrayDeque<>();
+
+ private final Deque<MethodType> callSiteTypes = new ArrayDeque<>();
+
+ private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName();
+
+ /**
+ * Apply specialization optimization. Try to explode arguments and call
+ * applies as calls if they just pass on the "arguments" array and
+ * "arguments" doesn't escape.
+ *
+ * @param compiler compiler
+ */
+ public ApplySpecialization(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ this.log = initLogger(compiler.getContext());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ @SuppressWarnings("serial")
+ private static class TransformFailedException extends RuntimeException {
+ TransformFailedException(final FunctionNode fn, final String message) {
+ super(massageURL(fn.getSource().getURL()) + '.' + fn.getName() + " => " + message, null, false, false);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ private static class AppliesFoundException extends RuntimeException {
+ AppliesFoundException() {
+ super("applies_found", null, false, false);
+ }
+ }
+
+ private static final AppliesFoundException HAS_APPLIES = new AppliesFoundException();
+
+ private boolean hasApplies(final FunctionNode functionNode) {
+ try {
+ functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterFunctionNode(final FunctionNode fn) {
+ return fn == functionNode;
+ }
+
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ if (isApply(callNode)) {
+ throw HAS_APPLIES;
+ }
+ return true;
+ }
+ });
+ } catch (final AppliesFoundException e) {
+ return true;
+ }
+
+ log.fine("There are no applies in ", DebugLogger.quote(functionNode.getName()), " - nothing to do.");
+ return false; // no applies
+ }
+
+ /**
+ * Arguments may only be used as args to the apply. Everything else is disqualified
+ * We cannot control arguments if they escape from the method and go into an unknown
+ * scope, thus we are conservative and treat any access to arguments outside the
+ * apply call as a case of "we cannot apply the optimization".
+ */
+ private static void checkValidTransform(final FunctionNode functionNode) {
+
+ final Set<Expression> argumentsFound = new HashSet<>();
+ final Deque<Set<Expression>> stack = new ArrayDeque<>();
+
+ //ensure that arguments is only passed as arg to apply
+ functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+
+ private boolean isCurrentArg(final Expression expr) {
+ return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
+ }
+
+ private boolean isArguments(final Expression expr) {
+ if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) {
+ argumentsFound.add(expr);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isParam(final String name) {
+ for (final IdentNode param : functionNode.getParameters()) {
+ if (param.getName().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ if (isParam(identNode.getName())) {
+ throw new TransformFailedException(lc.getCurrentFunction(), "parameter: " + identNode.getName());
+ }
+ // it's OK if 'argument' occurs as the current argument of an apply
+ if (isArguments(identNode) && !isCurrentArg(identNode)) {
+ throw new TransformFailedException(lc.getCurrentFunction(), "is 'arguments': " + identNode.getName());
+ }
+ return identNode;
+ }
+
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ final Set<Expression> callArgs = new HashSet<>();
+ if (isApply(callNode)) {
+ final List<Expression> argList = callNode.getArgs();
+ if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
+ throw new TransformFailedException(lc.getCurrentFunction(), "argument pattern not matched: " + argList);
+ }
+ callArgs.addAll(callNode.getArgs());
+ }
+ stack.push(callArgs);
+ return true;
+ }
+
+ @Override
+ public Node leaveCallNode(final CallNode callNode) {
+ stack.pop();
+ return callNode;
+ }
+ });
+ }
+
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ return !explodedArguments.isEmpty();
+ }
+
+ @Override
+ public Node leaveCallNode(final CallNode callNode) {
+ //apply needs to be a global symbol or we don't allow it
+
+ final List<IdentNode> newParams = explodedArguments.peek();
+ if (isApply(callNode)) {
+ final List<Expression> newArgs = new ArrayList<>();
+ for (final Expression arg : callNode.getArgs()) {
+ if (arg instanceof IdentNode && ARGUMENTS.equals(((IdentNode)arg).getName())) {
+ newArgs.addAll(newParams);
+ } else {
+ newArgs.add(arg);
+ }
+ }
+
+ changed.add(lc.getCurrentFunction().getId());
+
+ final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
+
+ if (log.isEnabled()) {
+ log.fine("Transformed ",
+ callNode,
+ " from apply to call => ",
+ newCallNode,
+ " in ",
+ DebugLogger.quote(lc.getCurrentFunction().getName()));
+ }
+
+ return newCallNode;
+ }
+
+ return callNode;
+ }
+
+ private void pushExplodedArgs(final FunctionNode functionNode) {
+ int start = 0;
+
+ final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode);
+ if (actualCallSiteType == null) {
+ throw new TransformFailedException(lc.getCurrentFunction(), "No callsite type");
+ }
+ assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType;
+
+ final TypeMap ptm = compiler.getTypeMap();
+ if (ptm.needsCallee()) {
+ start++;
+ }
+
+ start++; //we always uses this
+
+ final List<IdentNode> params = functionNode.getParameters();
+ final List<IdentNode> newParams = new ArrayList<>();
+ final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start);
+ for (int i = 0; i < to; i++) {
+ if (i >= params.size()) {
+ newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
+ } else {
+ newParams.add(params.get(i));
+ }
+ }
+
+ callSiteTypes.push(actualCallSiteType);
+ explodedArguments.push(newParams);
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ if (!USE_APPLY2CALL) {
+ return false;
+ }
+
+ if (!Global.isBuiltinFunctionPrototypeApply()) {
+ log.fine("Apply transform disabled: apply/call overridden");
+ assert !Global.isBuiltinFunctionPrototypeCall() : "call and apply should have the same SwitchPoint";
+ return false;
+ }
+
+ if (!compiler.isOnDemandCompilation()) {
+ return false;
+ }
+
+ if (functionNode.hasEval()) {
+ return false;
+ }
+
+ if (!hasApplies(functionNode)) {
+ return false;
+ }
+
+ if (log.isEnabled()) {
+ log.info("Trying to specialize apply to call in '",
+ functionNode.getName(),
+ "' params=",
+ functionNode.getParameters(),
+ " id=",
+ functionNode.getId(),
+ " source=",
+ massageURL(functionNode.getSource().getURL()));
+ }
+
+ try {
+ checkValidTransform(functionNode);
+ pushExplodedArgs(functionNode);
+ } catch (final TransformFailedException e) {
+ log.info("Failure: ", e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Try to do the apply to call transformation
+ * @return true if successful, false otherwise
+ */
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ FunctionNode newFunctionNode = functionNode;
+ final String functionName = newFunctionNode.getName();
+
+ if (changed.contains(newFunctionNode.getId())) {
+ newFunctionNode = newFunctionNode.clearFlag(lc, FunctionNode.USES_ARGUMENTS).
+ setFlag(lc, FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION).
+ setParameters(lc, explodedArguments.peek());
+
+ if (log.isEnabled()) {
+ log.info("Success: ",
+ massageURL(newFunctionNode.getSource().getURL()),
+ '.',
+ functionName,
+ "' id=",
+ newFunctionNode.getId(),
+ " params=",
+ callSiteTypes.peek());
+ }
+ }
+
+ callSiteTypes.pop();
+ explodedArguments.pop();
+
+ return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
+ }
+
+ private static boolean isApply(final CallNode callNode) {
+ final Expression f = callNode.getFunction();
+ return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty());
+ }
+
+ private static String massageURL(final URL url) {
+ if (url == null) {
+ return "<null>";
+ }
+ final String str = url.toString();
+ final int slash = str.lastIndexOf('/');
+ if (slash == -1) {
+ return str;
+ }
+ return str.substring(slash + 1);
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/AssignSymbols.java b/src/jdk/nashorn/internal/codegen/AssignSymbols.java
new file mode 100644
index 00000000..a4fb7bd1
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
+import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
+import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE;
+import static jdk.nashorn.internal.ir.Symbol.IS_CONST;
+import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
+import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
+import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
+import static jdk.nashorn.internal.ir.Symbol.IS_LET;
+import static jdk.nashorn.internal.ir.Symbol.IS_PARAM;
+import static jdk.nashorn.internal.ir.Symbol.IS_PROGRAM_LEVEL;
+import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE;
+import static jdk.nashorn.internal.ir.Symbol.IS_THIS;
+import static jdk.nashorn.internal.ir.Symbol.IS_VAR;
+import static jdk.nashorn.internal.ir.Symbol.KINDMASK;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ErrorManager;
+import jdk.nashorn.internal.runtime.JSErrorType;
+import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * This visitor assigns symbols to identifiers denoting variables. It does few more minor calculations that are only
+ * possible after symbols have been assigned; such is the transformation of "delete" and "typeof" operators into runtime
+ * nodes and counting of number of properties assigned to "this" in constructor functions. This visitor is also notable
+ * for what it doesn't do, most significantly it does no type calculations as in JavaScript variables can change types
+ * during runtime and as such symbols don't have types. Calculation of expression types is performed by a separate
+ * visitor.
+ */
+@Logger(name="symbols")
+final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable {
+ private final DebugLogger log;
+ private final boolean debug;
+
+ private static boolean isParamOrVar(final IdentNode identNode) {
+ final Symbol symbol = identNode.getSymbol();
+ return symbol.isParam() || symbol.isVar();
+ }
+
+ private static String name(final Node node) {
+ final String cn = node.getClass().getName();
+ final int lastDot = cn.lastIndexOf('.');
+ if (lastDot == -1) {
+ return cn;
+ }
+ return cn.substring(lastDot + 1);
+ }
+
+ /**
+ * Checks if various symbols that were provisionally marked as needing a slot ended up unused, and marks them as not
+ * needing a slot after all.
+ * @param functionNode the function node
+ * @return the passed in node, for easy chaining
+ */
+ private static FunctionNode removeUnusedSlots(final FunctionNode functionNode) {
+ if (!functionNode.needsCallee()) {
+ functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
+ }
+ if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
+ functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
+ }
+ // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
+ if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
+ final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
+ if(selfSymbol != null) {
+ if(selfSymbol.isFunctionSelf()) {
+ selfSymbol.setNeedsSlot(false);
+ selfSymbol.clearFlag(Symbol.IS_VAR);
+ }
+ } else {
+ assert functionNode.isProgram();
+ }
+ }
+ return functionNode;
+ }
+
+ private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
+ private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
+ private final Compiler compiler;
+
+ public AssignSymbols(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ this.log = initLogger(compiler.getContext());
+ this.debug = log.isEnabled();
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ /**
+ * Define symbols for all variable declarations at the top of the function scope. This way we can get around
+ * problems like
+ *
+ * while (true) {
+ * break;
+ * if (true) {
+ * var s;
+ * }
+ * }
+ *
+ * to an arbitrary nesting depth.
+ *
+ * see NASHORN-73
+ *
+ * @param functionNode the FunctionNode we are entering
+ * @param body the body of the FunctionNode we are entering
+ */
+ private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
+ // This visitor will assign symbol to all declared variables.
+ body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ protected boolean enterDefault(final Node node) {
+ // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
+ // This will also prevent visiting nested functions (as FunctionNode is an expression).
+ return !(node instanceof Expression);
+ }
+
+ @Override
+ public Node leaveVarNode(final VarNode varNode) {
+ final IdentNode ident = varNode.getName();
+ final boolean blockScoped = varNode.isBlockScoped();
+ if (blockScoped && lc.inUnprotectedSwitchContext()) {
+ throwUnprotectedSwitchError(varNode);
+ }
+ final Block block = blockScoped ? lc.getCurrentBlock() : body;
+ final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
+ if (varNode.isFunctionDeclaration()) {
+ symbol.setIsFunctionDeclaration();
+ }
+ return varNode.setName(ident.setSymbol(symbol));
+ }
+ });
+ }
+
+ private IdentNode compilerConstantIdentifier(final CompilerConstants cc) {
+ return createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc));
+ }
+
+ /**
+ * Creates an ident node for an implicit identifier within the function (one not declared in the script source
+ * code). These identifiers are defined with function's token and finish.
+ * @param name the name of the identifier
+ * @return an ident node representing the implicit identifier.
+ */
+ private IdentNode createImplicitIdentifier(final String name) {
+ final FunctionNode fn = lc.getCurrentFunction();
+ return new IdentNode(fn.getToken(), fn.getFinish(), name);
+ }
+
+ private Symbol createSymbol(final String name, final int flags) {
+ if ((flags & Symbol.KINDMASK) == IS_GLOBAL) {
+ //reuse global symbols so they can be hashed
+ Symbol global = globalSymbols.get(name);
+ if (global == null) {
+ global = new Symbol(name, flags);
+ globalSymbols.put(name, global);
+ }
+ return global;
+ }
+ return new Symbol(name, flags);
+ }
+
+ /**
+ * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
+ * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
+ * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
+ *
+ * @param name the ident node identifying the variable to initialize
+ * @param initConstant the compiler constant it is initialized to
+ * @param fn the function node the assignment is for
+ * @return a var node with the appropriate assignment
+ */
+ private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
+ final IdentNode init = compilerConstantIdentifier(initConstant);
+ assert init.getSymbol() != null && init.getSymbol().isBytecodeLocal();
+
+ final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);
+
+ final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
+ assert nameSymbol != null;
+
+ return (VarNode)synthVar.setName(name.setSymbol(nameSymbol)).accept(this);
+ }
+
+ private FunctionNode createSyntheticInitializers(final FunctionNode functionNode) {
+ final List<VarNode> syntheticInitializers = new ArrayList<>(2);
+
+ // Must visit the new var nodes in the context of the body. We could also just set the new statements into the
+ // block and then revisit the entire block, but that seems to be too much double work.
+ final Block body = functionNode.getBody();
+ lc.push(body);
+ try {
+ if (functionNode.usesSelfSymbol()) {
+ // "var fn = :callee"
+ syntheticInitializers.add(createSyntheticInitializer(functionNode.getIdent(), CALLEE, functionNode));
+ }
+
+ if (functionNode.needsArguments()) {
+ // "var arguments = :arguments"
+ syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
+ ARGUMENTS, functionNode));
+ }
+
+ if (syntheticInitializers.isEmpty()) {
+ return functionNode;
+ }
+
+ for(final ListIterator<VarNode> it = syntheticInitializers.listIterator(); it.hasNext();) {
+ it.set((VarNode)it.next().accept(this));
+ }
+ } finally {
+ lc.pop(body);
+ }
+
+ final List<Statement> stmts = body.getStatements();
+ final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
+ newStatements.addAll(syntheticInitializers);
+ newStatements.addAll(stmts);
+ return functionNode.setBody(lc, body.setStatements(lc, newStatements));
+ }
+
+ /**
+ * Defines a new symbol in the given block.
+ *
+ * @param block the block in which to define the symbol
+ * @param name name of symbol.
+ * @param origin origin node
+ * @param symbolFlags Symbol flags.
+ *
+ * @return Symbol for given name or null for redefinition.
+ */
+ private Symbol defineSymbol(final Block block, final String name, final Node origin, final int symbolFlags) {
+ int flags = symbolFlags;
+ final boolean isBlockScope = (flags & IS_LET) != 0 || (flags & IS_CONST) != 0;
+ final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
+
+ Symbol symbol;
+ final FunctionNode function;
+ if (isBlockScope) {
+ // block scoped variables always live in current block, no need to look for existing symbols in parent blocks.
+ symbol = block.getExistingSymbol(name);
+ function = lc.getCurrentFunction();
+ } else {
+ symbol = findSymbol(block, name);
+ function = lc.getFunction(block);
+ }
+
+ // Global variables are implicitly always scope variables too.
+ if (isGlobal) {
+ flags |= IS_SCOPE;
+ }
+
+ if (lc.getCurrentFunction().isProgram()) {
+ flags |= IS_PROGRAM_LEVEL;
+ }
+
+ final boolean isParam = (flags & KINDMASK) == IS_PARAM;
+ final boolean isVar = (flags & KINDMASK) == IS_VAR;
+
+ if (symbol != null) {
+ // Symbol was already defined. Check if it needs to be redefined.
+ if (isParam) {
+ if (!isLocal(function, symbol)) {
+ // Not defined in this function. Create a new definition.
+ symbol = null;
+ } else if (symbol.isParam()) {
+ // Duplicate parameter. Null return will force an error.
+ throw new AssertionError("duplicate parameter");
+ }
+ } else if (isVar) {
+ if (isBlockScope) {
+ // Check redeclaration in same block
+ if (symbol.hasBeenDeclared()) {
+ throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
+ } else {
+ symbol.setHasBeenDeclared();
+ // Set scope flag on top-level block scoped symbols
+ if (function.isProgram() && function.getBody() == block) {
+ symbol.setIsScope();
+ }
+ }
+ } else if ((flags & IS_INTERNAL) != 0) {
+ // Always create a new definition.
+ symbol = null;
+ } else {
+ // Found LET or CONST in parent scope of same function - s SyntaxError
+ if (symbol.isBlockScoped() && isLocal(lc.getCurrentFunction(), symbol)) {
+ throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
+ }
+ // Not defined in this function. Create a new definition.
+ if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
+ symbol = null;
+ }
+ }
+ }
+ }
+
+ if (symbol == null) {
+ // If not found, then create a new one.
+ final Block symbolBlock;
+
+ // Determine where to create it.
+ if (isVar && ((flags & IS_INTERNAL) != 0 || isBlockScope)) {
+ symbolBlock = block; //internal vars are always defined in the block closest to them
+ } else if (isGlobal) {
+ symbolBlock = lc.getOutermostFunction().getBody();
+ } else {
+ symbolBlock = lc.getFunctionBody(function);
+ }
+
+ // Create and add to appropriate block.
+ symbol = createSymbol(name, flags);
+ symbolBlock.putSymbol(lc, symbol);
+
+ if ((flags & IS_SCOPE) == 0) {
+ // Initial assumption; symbol can lose its slot later
+ symbol.setNeedsSlot(true);
+ }
+ } else if (symbol.less(flags)) {
+ symbol.setFlags(flags);
+ }
+
+ return symbol;
+ }
+
+ private <T extends Node> T end(final T node) {
+ return end(node, true);
+ }
+
+ private <T extends Node> T end(final T node, final boolean printNode) {
+ if (debug) {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("[LEAVE ").
+ append(name(node)).
+ append("] ").
+ append(printNode ? node.toString() : "").
+ append(" in '").
+ append(lc.getCurrentFunction().getName()).
+ append('\'');
+
+ if (node instanceof IdentNode) {
+ final Symbol symbol = ((IdentNode)node).getSymbol();
+ if (symbol == null) {
+ sb.append(" <NO SYMBOL>");
+ } else {
+ sb.append(" <symbol=").append(symbol).append('>');
+ }
+ }
+
+ log.unindent();
+ log.info(sb);
+ }
+
+ return node;
+ }
+
+ @Override
+ public boolean enterBlock(final Block block) {
+ start(block);
+
+ if (lc.isFunctionBody()) {
+ block.clearSymbols();
+ final FunctionNode fn = lc.getCurrentFunction();
+ if (isUnparsedFunction(fn)) {
+ // It's a skipped nested function. Just mark the symbols being used by it as being in use.
+ for(final String name: compiler.getScriptFunctionData(fn.getId()).getExternalSymbolNames()) {
+ nameIsUsed(name, null);
+ }
+ // Don't bother descending into it, it must be empty anyway.
+ assert block.getStatements().isEmpty();
+ return false;
+ }
+
+ enterFunctionBody();
+ }
+
+ return true;
+ }
+
+ private boolean isUnparsedFunction(final FunctionNode fn) {
+ return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+ }
+
+ @Override
+ public boolean enterCatchNode(final CatchNode catchNode) {
+ final IdentNode exception = catchNode.getException();
+ final Block block = lc.getCurrentBlock();
+
+ start(catchNode);
+
+ // define block-local exception variable
+ final String exname = exception.getName();
+ // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
+ // symbol is naturally internal, and should be treated as such.
+ final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
+ // IS_LET flag is required to make sure symbol is not visible outside catch block. However, we need to
+ // clear the IS_LET flag after creation to allow redefinition of symbol inside the catch block.
+ final Symbol symbol = defineSymbol(block, exname, catchNode, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
+ symbol.clearFlag(IS_LET);
+
+ return true;
+ }
+
+ private void enterFunctionBody() {
+ final FunctionNode functionNode = lc.getCurrentFunction();
+ final Block body = lc.getCurrentBlock();
+
+ initFunctionWideVariables(functionNode, body);
+
+ if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
+ // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
+ // anonymous.
+ final String name = functionNode.getIdent().getName();
+ assert name != null;
+ assert body.getExistingSymbol(name) == null;
+ defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
+ if(functionNode.allVarsInScope()) { // basically, has deep eval
+ lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+ }
+ }
+
+ acceptDeclarations(functionNode, body);
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ start(functionNode, false);
+
+ thisProperties.push(new HashSet<String>());
+
+ // Every function has a body, even the ones skipped on reparse (they have an empty one). We're
+ // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that
+ // are used in them.
+ assert functionNode.getBody() != null;
+
+ return true;
+ }
+
+ @Override
+ public boolean enterVarNode(final VarNode varNode) {
+ start(varNode);
+ // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function
+ // declarations as VarNodes, they are exception to the rule, as they need to have the symbol visible to the
+ // body of the declared function for self-reference.
+ if (varNode.isFunctionDeclaration()) {
+ defineVarIdent(varNode);
+ }
+ return true;
+ }
+
+ @Override
+ public Node leaveVarNode(final VarNode varNode) {
+ if (!varNode.isFunctionDeclaration()) {
+ defineVarIdent(varNode);
+ }
+ return super.leaveVarNode(varNode);
+ }
+
+ private void defineVarIdent(final VarNode varNode) {
+ final IdentNode ident = varNode.getName();
+ final int flags;
+ if (varNode.isAnonymousFunctionDeclaration()) {
+ flags = IS_INTERNAL;
+ } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
+ flags = IS_SCOPE;
+ } else {
+ flags = 0;
+ }
+ defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags);
+ }
+
+ private Symbol exceptionSymbol() {
+ return newObjectInternal(EXCEPTION_PREFIX);
+ }
+
+ /**
+ * This has to run before fix assignment types, store any type specializations for
+ * parameters, then turn them into objects for the generic version of this method.
+ *
+ * @param functionNode functionNode
+ */
+ private FunctionNode finalizeParameters(final FunctionNode functionNode) {
+ final List<IdentNode> newParams = new ArrayList<>();
+ final boolean isVarArg = functionNode.isVarArg();
+
+ final Block body = functionNode.getBody();
+ for (final IdentNode param : functionNode.getParameters()) {
+ final Symbol paramSymbol = body.getExistingSymbol(param.getName());
+ assert paramSymbol != null;
+ assert paramSymbol.isParam() : paramSymbol + " " + paramSymbol.getFlags();
+ newParams.add(param.setSymbol(paramSymbol));
+
+ // parameters should not be slots for a function that uses variable arity signature
+ if (isVarArg) {
+ paramSymbol.setNeedsSlot(false);
+ }
+ }
+
+ return functionNode.setParameters(lc, newParams);
+ }
+
+ /**
+ * Search for symbol in the lexical context starting from the given block.
+ * @param name Symbol name.
+ * @return Found symbol or null if not found.
+ */
+ private Symbol findSymbol(final Block block, final String name) {
+ for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
+ final Symbol symbol = blocks.next().getExistingSymbol(name);
+ if (symbol != null) {
+ return symbol;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Marks the current function as one using any global symbol. The function and all its parent functions will all be
+ * marked as needing parent scope.
+ * @see FunctionNode#needsParentScope()
+ */
+ private void functionUsesGlobalSymbol() {
+ for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
+ lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
+ }
+ }
+
+ /**
+ * Marks the current function as one using a scoped symbol. The block defining the symbol will be marked as needing
+ * its own scope to hold the variable. If the symbol is defined outside of the current function, it and all
+ * functions up to (but not including) the function containing the defining block will be marked as needing parent
+ * function scope.
+ * @see FunctionNode#needsParentScope()
+ */
+ private void functionUsesScopeSymbol(final Symbol symbol) {
+ final String name = symbol.getName();
+ for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
+ final LexicalContextNode node = contextNodeIter.next();
+ if (node instanceof Block) {
+ final Block block = (Block)node;
+ if (block.getExistingSymbol(name) != null) {
+ assert lc.contains(block);
+ lc.setBlockNeedsScope(block);
+ break;
+ }
+ } else if (node instanceof FunctionNode) {
+ lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE);
+ }
+ }
+ }
+
+ /**
+ * Declares that the current function is using the symbol.
+ * @param symbol the symbol used by the current function.
+ */
+ private void functionUsesSymbol(final Symbol symbol) {
+ assert symbol != null;
+ if (symbol.isScope()) {
+ if (symbol.isGlobal()) {
+ functionUsesGlobalSymbol();
+ } else {
+ functionUsesScopeSymbol(symbol);
+ }
+ } else {
+ assert !symbol.isGlobal(); // Every global is also scope
+ }
+ }
+
+ private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
+ defineSymbol(block, cc.symbolName(), null, flags).setNeedsSlot(true);
+ }
+
+ private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
+ initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
+ initCompileConstant(THIS, body, IS_PARAM | IS_THIS | HAS_OBJECT_VALUE);
+
+ if (functionNode.isVarArg()) {
+ initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
+ if (functionNode.needsArguments()) {
+ initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
+ defineSymbol(body, ARGUMENTS_VAR.symbolName(), null, IS_VAR | HAS_OBJECT_VALUE);
+ }
+ }
+
+ initParameters(functionNode, body);
+ initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
+ initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL);
+ }
+
+ /**
+ * Initialize parameters for function node.
+ * @param functionNode the function node
+ */
+ private void initParameters(final FunctionNode functionNode, final Block body) {
+ final boolean isVarArg = functionNode.isVarArg();
+ final boolean scopeParams = functionNode.allVarsInScope() || isVarArg;
+ for (final IdentNode param : functionNode.getParameters()) {
+ final Symbol symbol = defineSymbol(body, param.getName(), param, IS_PARAM);
+ if(scopeParams) {
+ // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored.
+ // It will force creation of scopes where they would otherwise not necessarily be needed (functions
+ // using arguments object and other variable arity functions). Tracked by JDK-8038942.
+ symbol.setIsScope();
+ assert symbol.hasSlot();
+ if(isVarArg) {
+ symbol.setNeedsSlot(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Is the symbol local to (that is, defined in) the specified function?
+ * @param function the function
+ * @param symbol the symbol
+ * @return true if the symbol is defined in the specified function
+ */
+ private boolean isLocal(final FunctionNode function, final Symbol symbol) {
+ final FunctionNode definingFn = lc.getDefiningFunction(symbol);
+ assert definingFn != null;
+ return definingFn == function;
+ }
+
+ private void checkConstAssignment(final IdentNode ident) {
+ // Check for reassignment of constant
+ final Symbol symbol = ident.getSymbol();
+ if (symbol.isConst()) {
+ throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident);
+ }
+ }
+
+ @Override
+ public Node leaveBinaryNode(final BinaryNode binaryNode) {
+ if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) {
+ checkConstAssignment((IdentNode) binaryNode.lhs());
+ }
+ switch (binaryNode.tokenType()) {
+ case ASSIGN:
+ return leaveASSIGN(binaryNode);
+ default:
+ return super.leaveBinaryNode(binaryNode);
+ }
+ }
+
+ private Node leaveASSIGN(final BinaryNode binaryNode) {
+ // If we're assigning a property of the this object ("this.foo = ..."), record it.
+ final Expression lhs = binaryNode.lhs();
+ if (lhs instanceof AccessNode) {
+ final AccessNode accessNode = (AccessNode) lhs;
+ final Expression base = accessNode.getBase();
+ if (base instanceof IdentNode) {
+ final Symbol symbol = ((IdentNode)base).getSymbol();
+ if(symbol.isThis()) {
+ thisProperties.peek().add(accessNode.getProperty());
+ }
+ }
+ }
+ return binaryNode;
+ }
+
+ @Override
+ public Node leaveUnaryNode(final UnaryNode unaryNode) {
+ if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) {
+ checkConstAssignment((IdentNode) unaryNode.getExpression());
+ }
+ switch (unaryNode.tokenType()) {
+ case DELETE:
+ return leaveDELETE(unaryNode);
+ case TYPEOF:
+ return leaveTYPEOF(unaryNode);
+ default:
+ return super.leaveUnaryNode(unaryNode);
+ }
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ // It's not necessary to guard the marking of symbols as locals with this "if" condition for
+ // correctness, it's just an optimization -- runtime type calculation is not used when the compilation
+ // is not an on-demand optimistic compilation, so we can skip locals marking then.
+ if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
+ // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
+ // compilation, and we're skipping parsing the function bodies for nested functions, this
+ // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
+ // symbol in the outer function named the same as one of the parameters, though.
+ if (lc.getFunction(block) == lc.getOutermostFunction()) {
+ for (final Symbol symbol: block.getSymbols()) {
+ if (!symbol.isScope()) {
+ assert symbol.isVar() || symbol.isParam();
+ compiler.declareLocalSymbol(symbol.getName());
+ }
+ }
+ }
+ }
+ return block;
+ }
+
+ private Node leaveDELETE(final UnaryNode unaryNode) {
+ final FunctionNode currentFunctionNode = lc.getCurrentFunction();
+ final boolean strictMode = currentFunctionNode.isStrict();
+ final Expression rhs = unaryNode.getExpression();
+ final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this);
+
+ Request request = Request.DELETE;
+ final List<Expression> args = new ArrayList<>();
+
+ if (rhs instanceof IdentNode) {
+ final IdentNode ident = (IdentNode)rhs;
+ // If this is a declared variable or a function parameter, delete always fails (except for globals).
+ final String name = ident.getName();
+ final Symbol symbol = ident.getSymbol();
+ final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel())));
+
+ if (failDelete && symbol.isThis()) {
+ return LiteralNode.newInstance(unaryNode, true).accept(this);
+ }
+ final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
+
+ if (!failDelete) {
+ args.add(compilerConstantIdentifier(SCOPE));
+ }
+ args.add(literalNode);
+ args.add(strictFlagNode);
+
+ if (failDelete) {
+ request = Request.FAIL_DELETE;
+ }
+ } else if (rhs instanceof AccessNode) {
+ final Expression base = ((AccessNode)rhs).getBase();
+ final String property = ((AccessNode)rhs).getProperty();
+
+ args.add(base);
+ args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this));
+ args.add(strictFlagNode);
+
+ } else if (rhs instanceof IndexNode) {
+ final IndexNode indexNode = (IndexNode)rhs;
+ final Expression base = indexNode.getBase();
+ final Expression index = indexNode.getIndex();
+
+ args.add(base);
+ args.add(index);
+ args.add(strictFlagNode);
+
+ } else {
+ return LiteralNode.newInstance(unaryNode, true).accept(this);
+ }
+ return new RuntimeNode(unaryNode, request, args).accept(this);
+ }
+
+ @Override
+ public Node leaveForNode(final ForNode forNode) {
+ if (forNode.isForIn()) {
+ forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
+ }
+
+ return end(forNode);
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ final FunctionNode finalizedFunction;
+ if (isUnparsedFunction(functionNode)) {
+ finalizedFunction = functionNode;
+ } else {
+ finalizedFunction =
+ markProgramBlock(
+ removeUnusedSlots(
+ createSyntheticInitializers(
+ finalizeParameters(
+ lc.applyTopFlags(functionNode))))
+ .setThisProperties(lc, thisProperties.pop().size()));
+ }
+ return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED);
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ if (identNode.isPropertyName()) {
+ return identNode;
+ }
+
+ final Symbol symbol = nameIsUsed(identNode.getName(), identNode);
+
+ if (!identNode.isInitializedHere()) {
+ symbol.increaseUseCount();
+ }
+
+ IdentNode newIdentNode = identNode.setSymbol(symbol);
+
+ // If a block-scoped var is used before its declaration mark it as dead.
+ // We can only statically detect this for local vars, cross-function symbols require runtime checks.
+ if (symbol.isBlockScoped() && !symbol.hasBeenDeclared() && !identNode.isDeclaredHere() && isLocal(lc.getCurrentFunction(), symbol)) {
+ newIdentNode = newIdentNode.markDead();
+ }
+
+ return end(newIdentNode);
+ }
+
+ private Symbol nameIsUsed(final String name, final IdentNode origin) {
+ final Block block = lc.getCurrentBlock();
+
+ Symbol symbol = findSymbol(block, name);
+
+ //If an existing symbol with the name is found, use that otherwise, declare a new one
+ if (symbol != null) {
+ log.info("Existing symbol = ", symbol);
+ if (symbol.isFunctionSelf()) {
+ final FunctionNode functionNode = lc.getDefiningFunction(symbol);
+ assert functionNode != null;
+ assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null;
+ lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+ }
+
+ // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
+ maybeForceScope(symbol);
+ } else {
+ log.info("No symbol exists. Declare as global: ", name);
+ symbol = defineSymbol(block, name, origin, IS_GLOBAL | IS_SCOPE);
+ }
+
+ functionUsesSymbol(symbol);
+ return symbol;
+ }
+
+ @Override
+ public Node leaveSwitchNode(final SwitchNode switchNode) {
+ // We only need a symbol for the tag if it's not an integer switch node
+ if(!switchNode.isUniqueInteger()) {
+ switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
+ }
+ return switchNode;
+ }
+
+ @Override
+ public Node leaveTryNode(final TryNode tryNode) {
+ tryNode.setException(exceptionSymbol());
+ if (tryNode.getFinallyBody() != null) {
+ tryNode.setFinallyCatchAll(exceptionSymbol());
+ }
+
+ end(tryNode);
+
+ return tryNode;
+ }
+
+ private Node leaveTYPEOF(final UnaryNode unaryNode) {
+ final Expression rhs = unaryNode.getExpression();
+
+ final List<Expression> args = new ArrayList<>();
+ if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) {
+ args.add(compilerConstantIdentifier(SCOPE));
+ args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
+ } else {
+ args.add(rhs);
+ args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
+ }
+
+ final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this);
+
+ end(unaryNode);
+
+ return runtimeNode;
+ }
+
+ private FunctionNode markProgramBlock(final FunctionNode functionNode) {
+ if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) {
+ return functionNode;
+ }
+
+ return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE));
+ }
+
+ /**
+ * If the symbol isn't already a scope symbol, but it needs to be (see {@link #symbolNeedsToBeScope(Symbol)}, it is
+ * promoted to a scope symbol and its block marked as needing a scope.
+ * @param symbol the symbol that might be scoped
+ */
+ private void maybeForceScope(final Symbol symbol) {
+ if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
+ Symbol.setSymbolIsScope(lc, symbol);
+ }
+ }
+
+ private Symbol newInternal(final CompilerConstants cc, final int flags) {
+ return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), null, IS_VAR | IS_INTERNAL | flags); //NASHORN-73
+ }
+
+ private Symbol newObjectInternal(final CompilerConstants cc) {
+ return newInternal(cc, HAS_OBJECT_VALUE);
+ }
+
+ private boolean start(final Node node) {
+ return start(node, true);
+ }
+
+ private boolean start(final Node node, final boolean printNode) {
+ if (debug) {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("[ENTER ").
+ append(name(node)).
+ append("] ").
+ append(printNode ? node.toString() : "").
+ append(" in '").
+ append(lc.getCurrentFunction().getName()).
+ append("'");
+ log.info(sb);
+ log.indent();
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines if the symbol has to be a scope symbol. In general terms, it has to be a scope symbol if it can only
+ * be reached from the current block by traversing a function node, a split node, or a with node.
+ * @param symbol the symbol checked for needing to be a scope symbol
+ * @return true if the symbol has to be a scope symbol.
+ */
+ private boolean symbolNeedsToBeScope(final Symbol symbol) {
+ if (symbol.isThis() || symbol.isInternal()) {
+ return false;
+ }
+
+ final FunctionNode func = lc.getCurrentFunction();
+ if ( func.allVarsInScope() || (!symbol.isBlockScoped() && func.isProgram())) {
+ return true;
+ }
+
+ boolean previousWasBlock = false;
+ for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
+ final LexicalContextNode node = it.next();
+ if (node instanceof FunctionNode || isSplitArray(node)) {
+ // We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
+ // It needs to be in scope.
+ return true;
+ } else if (node instanceof WithNode) {
+ if (previousWasBlock) {
+ // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
+ // preceded by a block, this means we're currently processing its expression, not its body,
+ // therefore it doesn't count.
+ return true;
+ }
+ previousWasBlock = false;
+ } else if (node instanceof Block) {
+ if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
+ // We reached the block that defines the symbol without reaching either the function boundary, or a
+ // WithNode. The symbol need not be scoped.
+ return false;
+ }
+ previousWasBlock = true;
+ } else {
+ previousWasBlock = false;
+ }
+ }
+ throw new AssertionError();
+ }
+
+ private static boolean isSplitArray(final LexicalContextNode expr) {
+ if(!(expr instanceof ArrayLiteralNode)) {
+ return false;
+ }
+ final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
+ return !(units == null || units.isEmpty());
+ }
+
+ private void throwUnprotectedSwitchError(final VarNode varNode) {
+ // Block scoped declarations in switch statements without explicit blocks should be declared
+ // in a common block that contains all the case clauses. We cannot support this without a
+ // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
+ // directly contained by switch node). As a temporary solution we throw a reference error here.
+ final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
+ throwParserException(msg, varNode);
+ }
+
+ private void throwParserException(final String message, final Node origin) {
+ if (origin == null) {
+ throw new ParserException(message);
+ }
+ final Source source = compiler.getSource();
+ final long token = origin.getToken();
+ final int line = source.getLine(origin.getStart());
+ final int column = source.getColumn(origin.getStart());
+ final String formatted = ErrorManager.format(message, source, line, column, token);
+ throw new ParserException(JSErrorType.SYNTAX_ERROR, formatted, source, line, column, token);
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/AstSerializer.java b/src/jdk/nashorn/internal/codegen/AstSerializer.java
new file mode 100644
index 00000000..dc35f964
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/AstSerializer.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.codegen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * This static utility class performs serialization of FunctionNode ASTs to a byte array.
+ * The format is a standard Java serialization stream, deflated.
+ */
+final class AstSerializer {
+ // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed
+ // and size.
+ private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
+ static byte[] serialize(final FunctionNode fn) {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
+ try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
+ oout.writeObject(removeInnerFunctionBodies(fn));
+ } catch (final IOException e) {
+ throw new AssertionError("Unexpected exception serializing function", e);
+ } finally {
+ deflater.end();
+ }
+ return out.toByteArray();
+ }
+
+ private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) {
+ return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public Node leaveBlock(final Block block) {
+ if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
+ return block.setStatements(lc, Collections.<Statement>emptyList());
+ }
+ return super.leaveBlock(block);
+ }
+ });
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/Attr.java b/src/jdk/nashorn/internal/codegen/Attr.java
deleted file mode 100644
index 61ccb712..00000000
--- a/src/jdk/nashorn/internal/codegen/Attr.java
+++ /dev/null
@@ -1,1947 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
-import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.LITERAL_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
-import static jdk.nashorn.internal.ir.Symbol.IS_ALWAYS_DEFINED;
-import static jdk.nashorn.internal.ir.Symbol.IS_CONSTANT;
-import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
-import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_LET;
-import static jdk.nashorn.internal.ir.Symbol.IS_PARAM;
-import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE;
-import static jdk.nashorn.internal.ir.Symbol.IS_THIS;
-import static jdk.nashorn.internal.ir.Symbol.IS_VAR;
-import static jdk.nashorn.internal.ir.Symbol.KINDMASK;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.AccessNode;
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.CaseNode;
-import jdk.nashorn.internal.ir.CatchNode;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.LexicalContextNode;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.SwitchNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
-import jdk.nashorn.internal.ir.TernaryNode;
-import jdk.nashorn.internal.ir.TryNode;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-
-/**
- * This is the attribution pass of the code generator. Attr takes Lowered IR,
- * that is, IR where control flow has been computed and high level to low level
- * substitions for operations have been performed.
- *
- * After Attr, every symbol will have a conservative correct type.
- *
- * Any expression that requires temporary storage as part of computation will
- * also be detected here and give a temporary symbol
- *
- * Types can be narrowed after Attr by Access Specialization in FinalizeTypes,
- * but in general, this is where the main symbol type information is
- * computed.
- */
-
-final class Attr extends NodeOperatorVisitor<LexicalContext> {
-
- /**
- * Local definitions in current block (to discriminate from function
- * declarations always defined in the function scope. This is for
- * "can be undefined" analysis.
- */
- private final Deque<Set<String>> localDefs;
-
- /**
- * Local definitions in current block to guard against cases like
- * NASHORN-467 when things can be undefined as they are used before
- * their local var definition. *sigh* JavaScript...
- */
- private final Deque<Set<String>> localUses;
-
- private final Deque<Type> returnTypes;
-
- private int catchNestingLevel;
-
- private static final DebugLogger LOG = new DebugLogger("attr");
- private static final boolean DEBUG = LOG.isEnabled();
-
- private final TemporarySymbols temporarySymbols;
-
- /**
- * Constructor.
- */
- Attr(final TemporarySymbols temporarySymbols) {
- super(new LexicalContext());
- this.temporarySymbols = temporarySymbols;
- this.localDefs = new ArrayDeque<>();
- this.localUses = new ArrayDeque<>();
- this.returnTypes = new ArrayDeque<>();
- }
-
- @Override
- protected boolean enterDefault(final Node node) {
- return start(node);
- }
-
- @Override
- protected Node leaveDefault(final Node node) {
- return end(node);
- }
-
- @Override
- public Node leaveAccessNode(final AccessNode accessNode) {
- //While Object type is assigned here, Access Specialization in FinalizeTypes may narrow this, that
- //is why we can't set the access node base to be an object here, that will ruin access specialization
- //for example for a.x | 17.
- return end(ensureSymbol(Type.OBJECT, accessNode));
- }
-
- private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
- initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL);
- initCompileConstant(THIS, body, IS_PARAM | IS_THIS, Type.OBJECT);
-
- if (functionNode.isVarArg()) {
- initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL);
- if (functionNode.needsArguments()) {
- initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
- final String argumentsName = ARGUMENTS_VAR.symbolName();
- newType(defineSymbol(body, argumentsName, IS_VAR | IS_ALWAYS_DEFINED), Type.typeFor(ARGUMENTS_VAR.type()));
- addLocalDef(argumentsName);
- }
- }
-
- initParameters(functionNode, body);
- initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
- initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT);
- }
-
-
- /**
- * This pushes all declarations (except for non-statements, i.e. for
- * node temporaries) to the top of the function scope. This way we can
- * get around problems like
- *
- * while (true) {
- * break;
- * if (true) {
- * var s;
- * }
- * }
- *
- * to an arbitrary nesting depth.
- *
- * see NASHORN-73
- *
- * @param functionNode the FunctionNode we are entering
- * @param body the body of the FunctionNode we are entering
- */
- private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
- // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
- // in a separate step above) and "var" declarations in for loop initializers.
- //
- // It also handles the case that a variable can be undefined, e.g
- // if (cond) {
- // x = x.y;
- // }
- // var x = 17;
- //
- // by making sure that no identifier has been found earlier in the body than the
- // declaration - if such is the case the identifier is flagged as caBeUndefined to
- // be safe if it turns into a local var. Otherwise corrupt bytecode results
-
- body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- private final Set<String> uses = new HashSet<>();
- private final Set<String> canBeUndefined = new HashSet<>();
-
- @Override
- public boolean enterFunctionNode(final FunctionNode nestedFn) {
- return false;
- }
-
- @Override
- public Node leaveIdentNode(final IdentNode identNode) {
- uses.add(identNode.getName());
- return identNode;
- }
-
- @Override
- public boolean enterVarNode(final VarNode varNode) {
- final String name = varNode.getName().getName();
- //if this is used before the var node, the var node symbol needs to be tagged as can be undefined
- if (uses.contains(name)) {
- canBeUndefined.add(name);
- }
-
- // all uses of the declared varnode inside the var node are potentially undefined
- // however this is a bit conservative as e.g. var x = 17; var x = 1 + x; does work
- if (!varNode.isFunctionDeclaration() && varNode.getInit() != null) {
- varNode.getInit().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public boolean enterIdentNode(final IdentNode identNode) {
- if (name.equals(identNode.getName())) {
- canBeUndefined.add(name);
- }
- return false;
- }
- });
- }
-
- return true;
- }
-
- @Override
- public Node leaveVarNode(final VarNode varNode) {
- // any declared symbols that aren't visited need to be typed as well, hence the list
- if (varNode.isStatement()) {
- final IdentNode ident = varNode.getName();
- final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR);
- if (canBeUndefined.contains(ident.getName())) {
- symbol.setType(Type.OBJECT);
- symbol.setCanBeUndefined();
- }
- functionNode.addDeclaredSymbol(symbol);
- if (varNode.isFunctionDeclaration()) {
- newType(symbol, FunctionNode.FUNCTION_TYPE);
- symbol.setIsFunctionDeclaration();
- }
- return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
- }
-
- return varNode;
- }
- });
- }
-
- private void enterFunctionBody() {
-
- final FunctionNode functionNode = lc.getCurrentFunction();
- final Block body = lc.getCurrentBlock();
-
- initFunctionWideVariables(functionNode, body);
-
- if (functionNode.isProgram()) {
- initFromPropertyMap(body);
- } else if (!functionNode.isDeclared()) {
- // It's neither declared nor program - it's a function expression then; assign it a self-symbol.
- assert functionNode.getSymbol() == null;
-
- final boolean anonymous = functionNode.isAnonymous();
- final String name = anonymous ? null : functionNode.getIdent().getName();
- if (!(anonymous || body.getExistingSymbol(name) != null)) {
- assert !anonymous && name != null;
- newType(defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF), Type.OBJECT);
- }
- }
-
- acceptDeclarations(functionNode, body);
- }
-
- @Override
- public boolean enterBlock(final Block block) {
- start(block);
- //ensure that we don't use information from a previous compile. This is very ugly TODO
- //the symbols in the block should really be stateless
- block.clearSymbols();
-
- if (lc.isFunctionBody()) {
- enterFunctionBody();
- }
- pushLocalsBlock();
-
- return true;
- }
-
- @Override
- public Node leaveBlock(final Block block) {
- popLocals();
- return end(block);
- }
-
- @Override
- public boolean enterCallNode(final CallNode callNode) {
- return start(callNode);
- }
-
- @Override
- public Node leaveCallNode(final CallNode callNode) {
- return end(ensureSymbol(callNode.getType(), callNode));
- }
-
- @Override
- public boolean enterCatchNode(final CatchNode catchNode) {
- final IdentNode exception = catchNode.getException();
- final Block block = lc.getCurrentBlock();
-
- start(catchNode);
- catchNestingLevel++;
-
- // define block-local exception variable
- final String exname = exception.getName();
- final Symbol def = defineSymbol(block, exname, IS_VAR | IS_LET | IS_ALWAYS_DEFINED);
- newType(def, Type.OBJECT); //we can catch anything, not just ecma exceptions
-
- addLocalDef(exname);
-
- return true;
- }
-
- @Override
- public Node leaveCatchNode(final CatchNode catchNode) {
- final IdentNode exception = catchNode.getException();
- final Block block = lc.getCurrentBlock();
- final Symbol symbol = findSymbol(block, exception.getName());
-
- catchNestingLevel--;
-
- assert symbol != null;
- return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol)));
- }
-
- /**
- * Declare the definition of a new symbol.
- *
- * @param name Name of symbol.
- * @param symbolFlags Symbol flags.
- *
- * @return Symbol for given name or null for redefinition.
- */
- private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
- int flags = symbolFlags;
- Symbol symbol = findSymbol(block, name); // Locate symbol.
- boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
-
- if (isGlobal) {
- flags |= IS_SCOPE;
- }
-
- final FunctionNode function = lc.getFunction(block);
- if (symbol != null) {
- // Symbol was already defined. Check if it needs to be redefined.
- if ((flags & KINDMASK) == IS_PARAM) {
- if (!isLocal(function, symbol)) {
- // Not defined in this function. Create a new definition.
- symbol = null;
- } else if (symbol.isParam()) {
- // Duplicate parameter. Null return will force an error.
- assert false : "duplicate parameter";
- return null;
- }
- } else if ((flags & KINDMASK) == IS_VAR) {
- if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) {
- // Always create a new definition.
- symbol = null;
- } else {
- // Not defined in this function. Create a new definition.
- if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
- symbol = null;
- }
- }
- }
- }
-
- if (symbol == null) {
- // If not found, then create a new one.
- Block symbolBlock;
-
- // Determine where to create it.
- if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
- symbolBlock = block; //internal vars are always defined in the block closest to them
- } else if (isGlobal) {
- symbolBlock = lc.getOutermostFunction().getBody();
- } else {
- symbolBlock = lc.getFunctionBody(function);
- }
-
- // Create and add to appropriate block.
- symbol = new Symbol(name, flags);
- symbolBlock.putSymbol(lc, symbol);
-
- if ((flags & Symbol.KINDMASK) != IS_GLOBAL) {
- symbol.setNeedsSlot(true);
- }
- } else if (symbol.less(flags)) {
- symbol.setFlags(flags);
- }
-
- return symbol;
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- start(functionNode, false);
-
- if (functionNode.isLazy()) {
- return false;
- }
-
- //an outermost function in our lexical context that is not a program (runScript)
- //is possible - it is a function being compiled lazily
- if (functionNode.isDeclared()) {
- final Iterator<Block> blocks = lc.getBlocks();
- if (blocks.hasNext()) {
- defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR);
- }
- }
-
- returnTypes.push(functionNode.getReturnType());
- pushLocalsFunction();
-
- return true;
- }
-
- @Override
- public Node leaveFunctionNode(final FunctionNode functionNode) {
- FunctionNode newFunctionNode = functionNode;
-
- final Block body = newFunctionNode.getBody();
-
- //look for this function in the parent block
- if (functionNode.isDeclared()) {
- final Iterator<Block> blocks = lc.getBlocks();
- if (blocks.hasNext()) {
- newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName()));
- }
- } else if (!functionNode.isProgram()) {
- final boolean anonymous = functionNode.isAnonymous();
- final String name = anonymous ? null : functionNode.getIdent().getName();
- if (anonymous || body.getExistingSymbol(name) != null) {
- newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode);
- } else {
- assert name != null;
- final Symbol self = body.getExistingSymbol(name);
- assert self != null && self.isFunctionSelf();
- newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, body.getExistingSymbol(name));
- }
- }
-
- //unknown parameters are promoted to object type.
- if (newFunctionNode.hasLazyChildren()) {
- //the final body has already been assigned as we have left the function node block body by now
- objectifySymbols(body);
- }
- newFunctionNode = finalizeParameters(newFunctionNode);
- newFunctionNode = finalizeTypes(newFunctionNode);
- for (final Symbol symbol : newFunctionNode.getDeclaredSymbols()) {
- if (symbol.getSymbolType().isUnknown()) {
- symbol.setType(Type.OBJECT);
- symbol.setCanBeUndefined();
- }
- }
-
- List<VarNode> syntheticInitializers = null;
-
- if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) {
- syntheticInitializers = new ArrayList<>(2);
- LOG.info("Accepting self symbol init for ", newFunctionNode.getName());
- // "var fn = :callee"
- syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode));
- }
-
- if (newFunctionNode.needsArguments()) {
- if (syntheticInitializers == null) {
- syntheticInitializers = new ArrayList<>(1);
- }
- // "var arguments = :arguments"
- syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
- ARGUMENTS, newFunctionNode));
- }
-
- if (syntheticInitializers != null) {
- final List<Statement> stmts = newFunctionNode.getBody().getStatements();
- final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
- newStatements.addAll(syntheticInitializers);
- newStatements.addAll(stmts);
- newFunctionNode = newFunctionNode.setBody(lc, newFunctionNode.getBody().setStatements(lc, newStatements));
- }
-
- if (returnTypes.peek().isUnknown()) {
- LOG.info("Unknown return type promoted to object");
- newFunctionNode = newFunctionNode.setReturnType(lc, Type.OBJECT);
- }
- final Type returnType = returnTypes.pop();
- newFunctionNode = newFunctionNode.setReturnType(lc, returnType.isUnknown() ? Type.OBJECT : returnType);
- newFunctionNode = newFunctionNode.setState(lc, CompilationState.ATTR);
-
- popLocals();
-
- end(newFunctionNode, false);
-
- return newFunctionNode;
- }
-
- /**
- * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
- * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
- * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
- *
- * @param name the ident node identifying the variable to initialize
- * @param initConstant the compiler constant it is initialized to
- * @param fn the function node the assignment is for
- * @return a var node with the appropriate assignment
- */
- private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
- final IdentNode init = compilerConstant(initConstant);
- assert init.getSymbol() != null && init.getSymbol().hasSlot();
-
- VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);
-
- final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
- assert nameSymbol != null;
-
- return synthVar.setName((IdentNode)name.setSymbol(lc, nameSymbol));
- }
-
- @Override
- public Node leaveIdentNode(final IdentNode identNode) {
- final String name = identNode.getName();
-
- if (identNode.isPropertyName()) {
- // assign a pseudo symbol to property name
- final Symbol pseudoSymbol = pseudoSymbol(name);
- LOG.info("IdentNode is property name -> assigning pseudo symbol ", pseudoSymbol);
- LOG.unindent();
- return end(identNode.setSymbol(lc, pseudoSymbol));
- }
-
- final Block block = lc.getCurrentBlock();
-
- Symbol symbol = findSymbol(block, name);
-
- //If an existing symbol with the name is found, use that otherwise, declare a new one
- if (symbol != null) {
- LOG.info("Existing symbol = ", symbol);
- if (symbol.isFunctionSelf()) {
- final FunctionNode functionNode = lc.getDefiningFunction(symbol);
- assert functionNode != null;
- assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null;
- lc.setFlag(functionNode.getBody(), Block.NEEDS_SELF_SYMBOL);
- newType(symbol, FunctionNode.FUNCTION_TYPE);
- } else if (!identNode.isInitializedHere()) {
- /*
- * See NASHORN-448, JDK-8016235
- *
- * Here is a use outside the local def scope
- * the inCatch check is a conservative approach to handle things that might have only been
- * defined in the try block, but with variable declarations, which due to JavaScript rules
- * have to be lifted up into the function scope outside the try block anyway, but as the
- * flow can fault at almost any place in the try block and get us to the catch block, all we
- * know is that we have a declaration, not a definition. This can be made better and less
- * conservative once we superimpose a CFG onto the AST.
- */
- if (!isLocalDef(name) || inCatch()) {
- newType(symbol, Type.OBJECT);
- symbol.setCanBeUndefined();
- }
- }
-
- // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
- maybeForceScope(symbol);
- } else {
- LOG.info("No symbol exists. Declare undefined: ", symbol);
- symbol = defineSymbol(block, name, IS_GLOBAL);
- // we have never seen this before, it can be undefined
- newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway?
- symbol.setCanBeUndefined();
- Symbol.setSymbolIsScope(lc, symbol);
- }
-
- setBlockScope(name, symbol);
-
- if (!identNode.isInitializedHere()) {
- symbol.increaseUseCount();
- }
- addLocalUse(identNode.getName());
-
- return end(identNode.setSymbol(lc, symbol));
- }
-
- private boolean inCatch() {
- return catchNestingLevel > 0;
- }
-
- /**
- * If the symbol isn't already a scope symbol, and it is either not local to the current function, or it is being
- * referenced from within a with block, we force it to be a scope symbol.
- * @param symbol the symbol that might be scoped
- */
- private void maybeForceScope(final Symbol symbol) {
- if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
- Symbol.setSymbolIsScope(lc, symbol);
- }
- }
-
- private boolean symbolNeedsToBeScope(Symbol symbol) {
- if (symbol.isThis() || symbol.isInternal()) {
- return false;
- }
- boolean previousWasBlock = false;
- for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
- final LexicalContextNode node = it.next();
- if (node instanceof FunctionNode) {
- // We reached the function boundary without seeing a definition for the symbol - it needs to be in
- // scope.
- return true;
- } else if (node instanceof WithNode) {
- if (previousWasBlock) {
- // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
- // preceded by a block, this means we're currently processing its expression, not its body,
- // therefore it doesn't count.
- return true;
- }
- previousWasBlock = false;
- } else if (node instanceof Block) {
- if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
- // We reached the block that defines the symbol without reaching either the function boundary, or a
- // WithNode. The symbol need not be scoped.
- return false;
- }
- previousWasBlock = true;
- } else {
- previousWasBlock = false;
- }
- }
- throw new AssertionError();
- }
-
- private void setBlockScope(final String name, final Symbol symbol) {
- assert symbol != null;
- if (symbol.isGlobal()) {
- setUsesGlobalSymbol();
- return;
- }
-
- if (symbol.isScope()) {
- Block scopeBlock = null;
- for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
- final LexicalContextNode node = contextNodeIter.next();
- if (node instanceof Block) {
- if (((Block)node).getExistingSymbol(name) != null) {
- scopeBlock = (Block)node;
- break;
- }
- } else if (node instanceof FunctionNode) {
- lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE);
- }
- }
-
- if (scopeBlock != null) {
- assert lc.contains(scopeBlock);
- lc.setBlockNeedsScope(scopeBlock);
- }
- }
- }
-
- /**
- * Marks the current function as one using any global symbol. The function and all its parent functions will all be
- * marked as needing parent scope.
- * @see #needsParentScope()
- */
- private void setUsesGlobalSymbol() {
- for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
- lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
- }
- }
-
- /**
- * Search for symbol in the lexical context starting from the given block.
- * @param name Symbol name.
- * @return Found symbol or null if not found.
- */
- private Symbol findSymbol(final Block block, final String name) {
- // Search up block chain to locate symbol.
-
- for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
- // Find name.
- final Symbol symbol = blocks.next().getExistingSymbol(name);
- // If found then we are good.
- if (symbol != null) {
- return symbol;
- }
- }
- return null;
- }
-
- @Override
- public Node leaveIndexNode(final IndexNode indexNode) {
- return end(ensureSymbol(Type.OBJECT, indexNode));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public Node leaveLiteralNode(final LiteralNode literalNode) {
- assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens
- assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported";
- final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
- if (literalNode instanceof ArrayLiteralNode) {
- ((ArrayLiteralNode)literalNode).analyze();
- }
- return end(literalNode.setSymbol(lc, symbol));
- }
-
- @Override
- public boolean enterObjectNode(final ObjectNode objectNode) {
- return start(objectNode);
- }
-
- @Override
- public Node leaveObjectNode(final ObjectNode objectNode) {
- return end(ensureSymbol(Type.OBJECT, objectNode));
- }
-
- @Override
- public Node leaveReturnNode(final ReturnNode returnNode) {
- final Expression expr = returnNode.getExpression();
- final Type returnType;
-
- if (expr != null) {
- //we can't do parameter specialization if we return something that hasn't been typed yet
- final Symbol symbol = expr.getSymbol();
- if (expr.getType().isUnknown() && symbol.isParam()) {
- symbol.setType(Type.OBJECT);
- }
-
- returnType = widestReturnType(returnTypes.pop(), symbol.getSymbolType());
- } else {
- returnType = Type.OBJECT; //undefined
- }
- LOG.info("Returntype is now ", returnType);
- returnTypes.push(returnType);
-
- end(returnNode);
-
- return returnNode;
- }
-
- @Override
- public Node leaveSwitchNode(final SwitchNode switchNode) {
- Type type = Type.UNKNOWN;
-
- final List<CaseNode> newCases = new ArrayList<>();
- for (final CaseNode caseNode : switchNode.getCases()) {
- final Node test = caseNode.getTest();
-
- CaseNode newCaseNode = caseNode;
- if (test != null) {
- if (test instanceof LiteralNode) {
- //go down to integers if we can
- final LiteralNode<?> lit = (LiteralNode<?>)test;
- if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) {
- if (JSType.isRepresentableAsInt(lit.getNumber())) {
- newCaseNode = caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
- }
- }
- } else {
- // the "all integer" case that CodeGenerator optimizes for currently assumes literals only
- type = Type.OBJECT;
- }
-
- final Type newCaseType = newCaseNode.getTest().getType();
- if (newCaseType.isBoolean()) {
- type = Type.OBJECT; //booleans and integers aren't assignment compatible
- } else {
- type = Type.widest(type, newCaseType);
- }
- }
-
- newCases.add(newCaseNode);
- }
-
- //only optimize for all integers
- if (!type.isInteger()) {
- type = Type.OBJECT;
- }
-
- switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
-
- end(switchNode);
-
- return switchNode.setCases(lc, newCases);
- }
-
- @Override
- public Node leaveTryNode(final TryNode tryNode) {
- tryNode.setException(exceptionSymbol());
-
- if (tryNode.getFinallyBody() != null) {
- tryNode.setFinallyCatchAll(exceptionSymbol());
- }
-
- end(tryNode);
-
- return tryNode;
- }
-
- @Override
- public boolean enterVarNode(final VarNode varNode) {
- start(varNode);
-
- final IdentNode ident = varNode.getName();
- final String name = ident.getName();
-
- final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR);
- assert symbol != null;
-
- // NASHORN-467 - use before definition of vars - conservative
- if (isLocalUse(ident.getName())) {
- newType(symbol, Type.OBJECT);
- symbol.setCanBeUndefined();
- }
-
- return true;
- }
-
- @Override
- public Node leaveVarNode(final VarNode varNode) {
- final Expression init = varNode.getInit();
- final IdentNode ident = varNode.getName();
- final String name = ident.getName();
-
- final Symbol symbol = findSymbol(lc.getCurrentBlock(), name);
- assert ident.getSymbol() == symbol;
-
- if (init == null) {
- // var x; with no init will be treated like a use of x by
- // leaveIdentNode unless we remove the name from the localdef list.
- removeLocalDef(name);
- return end(varNode);
- }
-
- addLocalDef(name);
-
- assert symbol != null;
-
- final IdentNode newIdent = (IdentNode)ident.setSymbol(lc, symbol);
-
- final VarNode newVarNode = varNode.setName(newIdent);
-
- final boolean isScript = lc.getDefiningFunction(symbol).isProgram(); //see NASHORN-56
- if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) {
- // Forbid integers as local vars for now as we have no way to treat them as undefined
- newType(symbol, init.getType());
- } else {
- newType(symbol, Type.OBJECT);
- }
-
- assert newVarNode.getName().hasType() : newVarNode + " has no type";
-
- return end(newVarNode);
- }
-
- @Override
- public Node leaveADD(final UnaryNode unaryNode) {
- return end(ensureSymbol(arithType(), unaryNode));
- }
-
- @Override
- public Node leaveBIT_NOT(final UnaryNode unaryNode) {
- return end(ensureSymbol(Type.INT, unaryNode));
- }
-
- @Override
- public Node leaveDECINC(final UnaryNode unaryNode) {
- // @see assignOffset
- final Type type = arithType();
- newType(unaryNode.rhs().getSymbol(), type);
- return end(ensureSymbol(type, unaryNode));
- }
-
- @Override
- public Node leaveDELETE(final UnaryNode unaryNode) {
- final FunctionNode currentFunctionNode = lc.getCurrentFunction();
- final boolean strictMode = currentFunctionNode.isStrict();
- final Expression rhs = unaryNode.rhs();
- final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this);
-
- Request request = Request.DELETE;
- final List<Expression> args = new ArrayList<>();
-
- if (rhs instanceof IdentNode) {
- // If this is a declared variable or a function parameter, delete always fails (except for globals).
- final String name = ((IdentNode)rhs).getName();
-
- final boolean failDelete = strictMode || rhs.getSymbol().isParam() || (rhs.getSymbol().isVar() && !isProgramLevelSymbol(name));
-
- if (failDelete && rhs.getSymbol().isThis()) {
- return LiteralNode.newInstance(unaryNode, true).accept(this);
- }
- final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
-
- if (!failDelete) {
- args.add(compilerConstant(SCOPE));
- }
- args.add(literalNode);
- args.add(strictFlagNode);
-
- if (failDelete) {
- request = Request.FAIL_DELETE;
- }
- } else if (rhs instanceof AccessNode) {
- final Expression base = ((AccessNode)rhs).getBase();
- final IdentNode property = ((AccessNode)rhs).getProperty();
-
- args.add(base);
- args.add((Expression)LiteralNode.newInstance(unaryNode, property.getName()).accept(this));
- args.add(strictFlagNode);
-
- } else if (rhs instanceof IndexNode) {
- final IndexNode indexNode = (IndexNode)rhs;
- final Expression base = indexNode.getBase();
- final Expression index = indexNode.getIndex();
-
- args.add(base);
- args.add(index);
- args.add(strictFlagNode);
-
- } else {
- return LiteralNode.newInstance(unaryNode, true).accept(this);
- }
-
- final RuntimeNode runtimeNode = new RuntimeNode(unaryNode, request, args);
- assert runtimeNode.getSymbol() == unaryNode.getSymbol(); //unary parent constructor should do this
-
- return leaveRuntimeNode(runtimeNode);
- }
-
- /**
- * Is the symbol denoted by the specified name in the current lexical context defined in the program level
- * @param name the name of the symbol
- * @return true if the symbol denoted by the specified name in the current lexical context defined in the program level.
- */
- private boolean isProgramLevelSymbol(final String name) {
- for(final Iterator<Block> it = lc.getBlocks(); it.hasNext();) {
- final Block next = it.next();
- if(next.getExistingSymbol(name) != null) {
- return next == lc.getFunctionBody(lc.getOutermostFunction());
- }
- }
- throw new AssertionError("Couldn't find symbol " + name + " in the context");
- }
-
- @Override
- public Node leaveNEW(final UnaryNode unaryNode) {
- return end(ensureSymbol(Type.OBJECT, unaryNode.setRHS(((CallNode)unaryNode.rhs()).setIsNew())));
- }
-
- @Override
- public Node leaveNOT(final UnaryNode unaryNode) {
- return end(ensureSymbol(Type.BOOLEAN, unaryNode));
- }
-
- private IdentNode compilerConstant(CompilerConstants cc) {
- return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc));
- }
-
- /**
- * Creates an ident node for an implicit identifier within the function (one not declared in the script source
- * code). These identifiers are defined with function's token and finish.
- * @param name the name of the identifier
- * @return an ident node representing the implicit identifier.
- */
- private IdentNode createImplicitIdentifier(final String name) {
- final FunctionNode fn = lc.getCurrentFunction();
- return new IdentNode(fn.getToken(), fn.getFinish(), name);
- }
-
- @Override
- public Node leaveTYPEOF(final UnaryNode unaryNode) {
- final Expression rhs = unaryNode.rhs();
-
- List<Expression> args = new ArrayList<>();
- if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) {
- args.add(compilerConstant(SCOPE));
- args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
- } else {
- args.add(rhs);
- args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
- }
-
- RuntimeNode runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
- assert runtimeNode.getSymbol() == unaryNode.getSymbol();
-
- runtimeNode = (RuntimeNode)leaveRuntimeNode(runtimeNode);
-
- end(unaryNode);
-
- return runtimeNode;
- }
-
- @Override
- public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
- return end(ensureSymbol(runtimeNode.getRequest().getReturnType(), runtimeNode));
- }
-
- @Override
- public Node leaveSUB(final UnaryNode unaryNode) {
- return end(ensureSymbol(arithType(), unaryNode));
- }
-
- @Override
- public Node leaveVOID(final UnaryNode unaryNode) {
- return end(ensureSymbol(Type.OBJECT, unaryNode));
- }
-
- /**
- * Add is a special binary, as it works not only on arithmetic, but for
- * strings etc as well.
- */
- @Override
- public Node leaveADD(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
-
- ensureTypeNotUnknown(lhs);
- ensureTypeNotUnknown(rhs);
- //even if we are adding two known types, this can overflow. i.e.
- //int and number -> number.
- //int and int are also number though.
- //something and object is object
- return end(ensureSymbol(Type.widest(arithType(), Type.widest(lhs.getType(), rhs.getType())), binaryNode));
- }
-
- @Override
- public Node leaveAND(final BinaryNode binaryNode) {
- return end(ensureSymbol(Type.OBJECT, binaryNode));
- }
-
- /**
- * This is a helper called before an assignment.
- * @param binaryNode assignment node
- */
- private boolean enterAssignmentNode(final BinaryNode binaryNode) {
- start(binaryNode);
-
- return true;
- }
-
-
- /**
- * This assign helper is called after an assignment, when all children of
- * the assign has been processed. It fixes the types and recursively makes
- * sure that everyhing has slots that should have them in the chain.
- *
- * @param binaryNode assignment node
- */
- private Node leaveAssignmentNode(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
- final Type type;
-
- if (lhs instanceof IdentNode) {
- final Block block = lc.getCurrentBlock();
- final IdentNode ident = (IdentNode)lhs;
- final String name = ident.getName();
- final Symbol symbol = findSymbol(block, name);
-
- if (symbol == null) {
- defineSymbol(block, name, IS_GLOBAL);
- } else {
- maybeForceScope(symbol);
- }
-
- addLocalDef(name);
- }
-
- if (rhs.getType().isNumeric()) {
- type = Type.widest(lhs.getType(), rhs.getType());
- } else {
- type = Type.OBJECT; //force lhs to be an object if not numeric assignment, e.g. strings too.
- }
-
- newType(lhs.getSymbol(), type);
- return end(ensureSymbol(type, binaryNode));
- }
-
- private boolean isLocal(FunctionNode function, Symbol symbol) {
- final FunctionNode definingFn = lc.getDefiningFunction(symbol);
- // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local
- return definingFn == null || definingFn == function;
- }
-
- @Override
- public boolean enterASSIGN(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN(final BinaryNode binaryNode) {
- return leaveAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_ADD(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
-
- final Type widest = Type.widest(lhs.getType(), rhs.getType());
- //Type.NUMBER if we can't prove that the add doesn't overflow. todo
- return leaveSelfModifyingAssignmentNode(binaryNode, widest.isNumeric() ? Type.NUMBER : Type.OBJECT);
- }
-
- @Override
- public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_BIT_AND(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_BIT_OR(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_BIT_XOR(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_DIV(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_MOD(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_MUL(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_SAR(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_SHL(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_SHR(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
- return enterAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveASSIGN_SUB(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode);
- }
-
- @Override
- public Node leaveBIT_AND(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.INT));
- }
-
- @Override
- public Node leaveBIT_OR(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.INT));
- }
-
- @Override
- public Node leaveBIT_XOR(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.INT));
- }
-
- @Override
- public Node leaveCOMMARIGHT(final BinaryNode binaryNode) {
- return leaveComma(binaryNode, binaryNode.rhs());
- }
-
- @Override
- public Node leaveCOMMALEFT(final BinaryNode binaryNode) {
- return leaveComma(binaryNode, binaryNode.lhs());
- }
-
- private Node leaveComma(final BinaryNode commaNode, final Expression effectiveExpr) {
- ensureTypeNotUnknown(effectiveExpr);
- return end(ensureSymbol(effectiveExpr.getType(), commaNode));
- }
-
- @Override
- public Node leaveDIV(final BinaryNode binaryNode) {
- return leaveBinaryArithmetic(binaryNode);
- }
-
- private Node leaveCmp(final BinaryNode binaryNode) {
- ensureTypeNotUnknown(binaryNode.lhs());
- ensureTypeNotUnknown(binaryNode.rhs());
- Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
- ensureSymbol(widest, binaryNode.lhs());
- ensureSymbol(widest, binaryNode.rhs());
- return end(ensureSymbol(Type.BOOLEAN, binaryNode));
- }
-
- private Node coerce(final BinaryNode binaryNode, final Type operandType, final Type destType) {
- // TODO we currently don't support changing inferred type based on uses, only on
- // definitions. we would need some additional logic. We probably want to do that
- // in the future, if e.g. a specialized method gets parameter that is only used
- // as, say, an int : function(x) { return x & 4711 }, and x is not defined in
- // the function. to make this work, uncomment the following two type inferences
- // and debug.
- //newType(binaryNode.lhs().getSymbol(), operandType);
- //newType(binaryNode.rhs().getSymbol(), operandType);
- return ensureSymbol(destType, binaryNode);
- }
-
- private Node coerce(final BinaryNode binaryNode, final Type type) {
- return coerce(binaryNode, type, type);
- }
-
- //leave a binary node and inherit the widest type of lhs , rhs
- private Node leaveBinaryArithmetic(final BinaryNode binaryNode) {
- assert !Compiler.shouldUseIntegerArithmetic();
- return end(coerce(binaryNode, Type.NUMBER));
- }
-
- @Override
- public Node leaveEQ(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveEQ_STRICT(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveGE(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveGT(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveIN(final BinaryNode binaryNode) {
- return leaveBinaryRuntimeOperator(binaryNode, Request.IN);
- }
-
- @Override
- public Node leaveINSTANCEOF(final BinaryNode binaryNode) {
- return leaveBinaryRuntimeOperator(binaryNode, Request.INSTANCEOF);
- }
-
- private Node leaveBinaryRuntimeOperator(final BinaryNode binaryNode, final Request request) {
- try {
- // Don't do a full RuntimeNode.accept, as we don't want to double-visit the binary node operands
- return leaveRuntimeNode(new RuntimeNode(binaryNode, request));
- } finally {
- end(binaryNode);
- }
- }
-
- @Override
- public Node leaveLE(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveLT(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveMOD(final BinaryNode binaryNode) {
- return leaveBinaryArithmetic(binaryNode);
- }
-
- @Override
- public Node leaveMUL(final BinaryNode binaryNode) {
- return leaveBinaryArithmetic(binaryNode);
- }
-
- @Override
- public Node leaveNE(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveNE_STRICT(final BinaryNode binaryNode) {
- return leaveCmp(binaryNode);
- }
-
- @Override
- public Node leaveOR(final BinaryNode binaryNode) {
- return end(ensureSymbol(Type.OBJECT, binaryNode));
- }
-
- @Override
- public Node leaveSAR(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.INT));
- }
-
- @Override
- public Node leaveSHL(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.INT));
- }
-
- @Override
- public Node leaveSHR(final BinaryNode binaryNode) {
- return end(coerce(binaryNode, Type.LONG));
- }
-
- @Override
- public Node leaveSUB(final BinaryNode binaryNode) {
- return leaveBinaryArithmetic(binaryNode);
- }
-
- @Override
- public Node leaveForNode(final ForNode forNode) {
- if (forNode.isForIn()) {
- forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.typeFor(ITERATOR_PREFIX.type()))); //NASHORN-73
- /*
- * Iterators return objects, so we need to widen the scope of the
- * init variable if it, for example, has been assigned double type
- * see NASHORN-50
- */
- newType(forNode.getInit().getSymbol(), Type.OBJECT);
- }
-
- end(forNode);
-
- return forNode;
- }
-
- @Override
- public Node leaveTernaryNode(final TernaryNode ternaryNode) {
- final Expression trueExpr = ternaryNode.getTrueExpression();
- final Expression falseExpr = ternaryNode.getFalseExpression();
-
- ensureTypeNotUnknown(trueExpr);
- ensureTypeNotUnknown(falseExpr);
-
- final Type type = widestReturnType(trueExpr.getType(), falseExpr.getType());
- return end(ensureSymbol(type, ternaryNode));
- }
-
- /**
- * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to
- * anything other than Object. Also, widening a numeric type to an object type must widen to Object proper and not
- * any more specific subclass (e.g. widest of int/long/double and String is Object).
- * @param t1 type 1
- * @param t2 type 2
- * @return wider of t1 and t2, except if one is boolean and the other is neither boolean nor unknown, or if one is
- * numeric and the other is neither numeric nor unknown in which case {@code Type.OBJECT} is returned.
- */
- private static Type widestReturnType(final Type t1, final Type t2) {
- if (t1.isUnknown()) {
- return t2;
- } else if (t2.isUnknown()) {
- return t1;
- } else if (t1.isBoolean() != t2.isBoolean() || t1.isNumeric() != t2.isNumeric()) {
- return Type.OBJECT;
- }
- return Type.widest(t1, t2);
- }
-
- private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
- final Class<?> type = cc.type();
- // Must not call this method for constants with no explicit types; use the one with (..., Type) signature instead.
- assert type != null;
- initCompileConstant(cc, block, flags, Type.typeFor(type));
- }
-
- private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags, final Type type) {
- final Symbol symbol = defineSymbol(block, cc.symbolName(), flags);
- symbol.setTypeOverride(type);
- symbol.setNeedsSlot(true);
- }
-
- /**
- * Initialize parameters for function node. This may require specializing
- * types if a specialization profile is known
- *
- * @param functionNode the function node
- */
- private void initParameters(final FunctionNode functionNode, final Block body) {
- int pos = 0;
- for (final IdentNode param : functionNode.getParameters()) {
- addLocalDef(param.getName());
-
- final Type callSiteParamType = functionNode.getHints().getParameterType(pos);
- int flags = IS_PARAM;
- if (callSiteParamType != null) {
- LOG.info("Param ", param, " has a callsite type ", callSiteParamType, ". Using that.");
- flags |= Symbol.IS_SPECIALIZED_PARAM;
- }
-
- final Symbol paramSymbol = defineSymbol(body, param.getName(), flags);
- assert paramSymbol != null;
-
- newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType);
-
- LOG.info("Initialized param ", pos, "=", paramSymbol);
- pos++;
- }
-
- }
-
- /**
- * This has to run before fix assignment types, store any type specializations for
- * paramters, then turn then to objects for the generic version of this method
- *
- * @param functionNode functionNode
- */
- private FunctionNode finalizeParameters(final FunctionNode functionNode) {
- final List<IdentNode> newParams = new ArrayList<>();
- final boolean isVarArg = functionNode.isVarArg();
- final int nparams = functionNode.getParameters().size();
-
- int specialize = 0;
- int pos = 0;
- for (final IdentNode param : functionNode.getParameters()) {
- final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName());
- assert paramSymbol != null;
- assert paramSymbol.isParam();
- newParams.add((IdentNode)param.setSymbol(lc, paramSymbol));
-
- assert paramSymbol != null;
- Type type = functionNode.getHints().getParameterType(pos);
- if (type == null) {
- type = Type.OBJECT;
- }
-
- // if we know that a parameter is only used as a certain type throughout
- // this function, we can tell the runtime system that no matter what the
- // call site is, use this information:
- // we also need more than half of the parameters to be specializable
- // for the heuristic to be worth it, and we need more than one use of
- // the parameter to consider it, i.e. function(x) { call(x); } doens't count
- if (paramSymbol.getUseCount() > 1 && !paramSymbol.getSymbolType().isObject()) {
- LOG.finest("Parameter ", param, " could profit from specialization to ", paramSymbol.getSymbolType());
- specialize++;
- }
-
- newType(paramSymbol, Type.widest(type, paramSymbol.getSymbolType()));
-
- // parameters should not be slots for a function that uses variable arity signature
- if (isVarArg) {
- paramSymbol.setNeedsSlot(false);
- }
-
- pos++;
- }
-
- FunctionNode newFunctionNode = functionNode;
-
- if (nparams == 0 || (specialize * 2) < nparams) {
- newFunctionNode = newFunctionNode.clearSnapshot(lc);
- }
-
- return newFunctionNode.setParameters(lc, newParams);
- }
-
- /**
- * Move any properties from a global map into the scope of this method
- * @param block the function node body for which to init scope vars
- */
- private void initFromPropertyMap(final Block block) {
- // For a script, add scope symbols as defined in the property map
-
- final PropertyMap map = Context.getGlobalMap();
-
- for (final Property property : map.getProperties()) {
- final String key = property.getKey();
- final Symbol symbol = defineSymbol(block, key, IS_GLOBAL);
- newType(symbol, Type.OBJECT);
- LOG.info("Added global symbol from property map ", symbol);
- }
- }
-
- private static void ensureTypeNotUnknown(final Expression node) {
-
- final Symbol symbol = node.getSymbol();
-
- LOG.info("Ensure type not unknown for: ", symbol);
-
- /*
- * Note that not just unknowns, but params need to be blown
- * up to objects, because we can have something like
- *
- * function f(a) {
- * var b = ~a; //b and a are inferred to be int
- * return b;
- * }
- *
- * In this case, it would be correct to say that "if you have
- * an int at the callsite, just pass it".
- *
- * However
- *
- * function f(a) {
- * var b = ~a; //b and a are inferred to be int
- * return b == 17; //b is still inferred to be int.
- * }
- *
- * can be called with f("17") and if we assume that b is an
- * int and don't blow it up to an object in the comparison, we
- * are screwed. I hate JavaScript.
- *
- * This check has to be done for any operation that might take
- * objects as parameters, for example +, but not *, which is known
- * to coerce types into doubles
- */
- if (node.getType().isUnknown() || (symbol.isParam() && !symbol.isSpecializedParam())) {
- newType(symbol, Type.OBJECT);
- symbol.setCanBeUndefined();
- }
- }
-
- private static Symbol pseudoSymbol(final String name) {
- return new Symbol(name, 0, Type.OBJECT);
- }
-
- private Symbol exceptionSymbol() {
- return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(EXCEPTION_PREFIX.type()));
- }
-
- /**
- * Return the type that arithmetic ops should use. Until we have implemented better type
- * analysis (range based) or overflow checks that are fast enough for int arithmetic,
- * this is the number type
- * @return the arithetic type
- */
- private static Type arithType() {
- return Compiler.shouldUseIntegerArithmetic() ? Type.INT : Type.NUMBER;
- }
-
- /**
- * If types have changed, we can have failed to update vars. For example
- *
- * var x = 17; //x is int
- * x = "apa"; //x is object. This will be converted fine
- *
- * @param functionNode
- */
- private FunctionNode finalizeTypes(final FunctionNode functionNode) {
- final Set<Node> changed = new HashSet<>();
- FunctionNode currentFunctionNode = functionNode;
- do {
- changed.clear();
- final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-
- private Expression widen(final Expression node, final Type to) {
- if (node instanceof LiteralNode) {
- return node;
- }
- Type from = node.getType();
- if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) {
- LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to);
- Symbol symbol = node.getSymbol();
- if (symbol.isShared() && symbol.wouldChangeType(to)) {
- symbol = temporarySymbols.getTypedTemporarySymbol(to);
- }
- newType(symbol, to);
- final Expression newNode = node.setSymbol(lc, symbol);
- changed.add(newNode);
- return newNode;
- }
- return node;
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode node) {
- return !node.isLazy();
- }
-
- //
- // Eg.
- //
- // var d = 17;
- // var e;
- // e = d; //initially typed as int for node type, should retype as double
- // e = object;
- //
- // var d = 17;
- // var e;
- // e -= d; //initially type number, should number remain with a final conversion supplied by Store. ugly, but the computation result of the sub is numeric
- // e = object;
- //
- @SuppressWarnings("fallthrough")
- @Override
- public Node leaveBinaryNode(final BinaryNode binaryNode) {
- final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
- BinaryNode newBinaryNode = binaryNode;
-
- if (isAdd(binaryNode)) {
- newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
- if (newBinaryNode.getType().isObject() && !isAddString(newBinaryNode)) {
- return new RuntimeNode(newBinaryNode, Request.ADD);
- }
- } else if (binaryNode.isComparison()) {
- final Expression lhs = newBinaryNode.lhs();
- final Expression rhs = newBinaryNode.rhs();
-
- Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
-
- boolean newRuntimeNode = false, finalized = false;
- switch (newBinaryNode.tokenType()) {
- case EQ_STRICT:
- case NE_STRICT:
- if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
- newRuntimeNode = true;
- cmpWidest = Type.OBJECT;
- finalized = true;
- }
- //fallthru
- default:
- if (newRuntimeNode || cmpWidest.isObject()) {
- return new RuntimeNode(newBinaryNode, Request.requestFor(binaryNode)).setIsFinal(finalized);
- }
- break;
- }
-
- return newBinaryNode;
- } else {
- if (!binaryNode.isAssignment() || binaryNode.isSelfModifying()) {
- return newBinaryNode;
- }
- checkThisAssignment(binaryNode);
- newBinaryNode = newBinaryNode.setLHS(widen(newBinaryNode.lhs(), widest));
- newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
- }
-
- return newBinaryNode;
-
- }
-
- private boolean isAdd(final Node node) {
- return node.isTokenType(TokenType.ADD);
- }
-
- /**
- * Determine if the outcome of + operator is a string.
- *
- * @param node Node to test.
- * @return true if a string result.
- */
- private boolean isAddString(final Node node) {
- if (node instanceof BinaryNode && isAdd(node)) {
- final BinaryNode binaryNode = (BinaryNode)node;
- final Node lhs = binaryNode.lhs();
- final Node rhs = binaryNode.rhs();
-
- return isAddString(lhs) || isAddString(rhs);
- }
-
- return node instanceof LiteralNode<?> && ((LiteralNode<?>)node).isString();
- }
-
- private void checkThisAssignment(final BinaryNode binaryNode) {
- if (binaryNode.isAssignment()) {
- if (binaryNode.lhs() instanceof AccessNode) {
- final AccessNode accessNode = (AccessNode) binaryNode.lhs();
-
- if (accessNode.getBase().getSymbol().isThis()) {
- lc.getCurrentFunction().addThisProperty(accessNode.getProperty().getName());
- }
- }
- }
- }
- });
- lc.replace(currentFunctionNode, newFunctionNode);
- currentFunctionNode = newFunctionNode;
- } while (!changed.isEmpty());
-
- return currentFunctionNode;
- }
-
- private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode) {
- return leaveSelfModifyingAssignmentNode(binaryNode, binaryNode.getWidestOperationType());
- }
-
- private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode, final Type destType) {
- //e.g. for -=, Number, no wider, destType (binaryNode.getWidestOperationType()) is the coerce type
- final Expression lhs = binaryNode.lhs();
-
- newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType
-
- return end(ensureSymbol(destType, binaryNode));
- }
-
- private Expression ensureSymbol(final Type type, final Expression expr) {
- LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
- return temporarySymbols.ensureSymbol(lc, type, expr);
- }
-
- private Symbol newInternal(final String name, final Type type) {
- final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
- iter.setType(type); // NASHORN-73
- return iter;
- }
-
- private static void newType(final Symbol symbol, final Type type) {
- final Type oldType = symbol.getSymbolType();
- symbol.setType(type);
-
- if (symbol.getSymbolType() != oldType) {
- LOG.info("New TYPE ", type, " for ", symbol," (was ", oldType, ")");
- }
-
- if (symbol.isParam()) {
- symbol.setType(type);
- LOG.info("Param type change ", symbol);
- }
- }
-
- private void pushLocalsFunction() {
- localDefs.push(new HashSet<String>());
- localUses.push(new HashSet<String>());
- }
-
- private void pushLocalsBlock() {
- localDefs.push(new HashSet<>(localDefs.peek()));
- localUses.push(new HashSet<>(localUses.peek()));
- }
-
- private void popLocals() {
- localDefs.pop();
- localUses.pop();
- }
-
- private boolean isLocalDef(final String name) {
- return localDefs.peek().contains(name);
- }
-
- private void addLocalDef(final String name) {
- LOG.info("Adding local def of symbol: '", name, "'");
- localDefs.peek().add(name);
- }
-
- private void removeLocalDef(final String name) {
- LOG.info("Removing local def of symbol: '", name, "'");
- localDefs.peek().remove(name);
- }
-
- private boolean isLocalUse(final String name) {
- return localUses.peek().contains(name);
- }
-
- private void addLocalUse(final String name) {
- LOG.info("Adding local use of symbol: '", name, "'");
- localUses.peek().add(name);
- }
-
- /**
- * Pessimistically promote all symbols in current function node to Object types
- * This is done when the function contains unevaluated black boxes such as
- * lazy sub-function nodes that have not been compiled.
- *
- * @param body body for the function node we are leaving
- */
- private static void objectifySymbols(final Block body) {
- body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- private void toObject(final Block block) {
- for (final Symbol symbol : block.getSymbols()) {
- if (!symbol.isTemp()) {
- newType(symbol, Type.OBJECT);
- }
- }
- }
-
- @Override
- public boolean enterBlock(final Block block) {
- toObject(block);
- return true;
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode node) {
- return false;
- }
- });
- }
-
- private static String name(final Node node) {
- final String cn = node.getClass().getName();
- int lastDot = cn.lastIndexOf('.');
- if (lastDot == -1) {
- return cn;
- }
- return cn.substring(lastDot + 1);
- }
-
- private boolean start(final Node node) {
- return start(node, true);
- }
-
- private boolean start(final Node node, final boolean printNode) {
- if (DEBUG) {
- final StringBuilder sb = new StringBuilder();
-
- sb.append("[ENTER ").
- append(name(node)).
- append("] ").
- append(printNode ? node.toString() : "").
- append(" in '").
- append(lc.getCurrentFunction().getName()).
- append("'");
- LOG.info(sb);
- LOG.indent();
- }
-
- return true;
- }
-
- private <T extends Node> T end(final T node) {
- return end(node, true);
- }
-
- private <T extends Node> T end(final T node, final boolean printNode) {
- if(node instanceof Statement) {
- // If we're done with a statement, all temporaries can be reused.
- temporarySymbols.reuse();
- }
- if (DEBUG) {
- final StringBuilder sb = new StringBuilder();
-
- sb.append("[LEAVE ").
- append(name(node)).
- append("] ").
- append(printNode ? node.toString() : "").
- append(" in '").
- append(lc.getCurrentFunction().getName()).
- append('\'');
-
- if (node instanceof Expression) {
- final Symbol symbol = ((Expression)node).getSymbol();
- if (symbol == null) {
- sb.append(" <NO SYMBOL>");
- } else {
- sb.append(" <symbol=").append(symbol).append('>');
- }
- }
-
- LOG.unindent();
- LOG.info(sb);
- }
-
- return node;
- }
-}
diff --git a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
index ad9bdb07..5c8f9645 100644
--- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
+++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
@@ -32,10 +32,10 @@ import static jdk.nashorn.internal.codegen.Condition.LE;
import static jdk.nashorn.internal.codegen.Condition.LT;
import static jdk.nashorn.internal.codegen.Condition.NE;
-import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.UnaryNode;
/**
@@ -57,7 +57,7 @@ final class BranchOptimizer {
}
private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) {
- final Expression rhs = unaryNode.rhs();
+ final Expression rhs = unaryNode.getExpression();
switch (unaryNode.tokenType()) {
case NOT:
@@ -71,13 +71,7 @@ final class BranchOptimizer {
break;
}
- // convert to boolean
- codegen.load(unaryNode, Type.BOOLEAN);
- if (state) {
- method.ifne(label);
- } else {
- method.ifeq(label);
- }
+ loadTestAndJump(unaryNode, label, state);
}
private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) {
@@ -88,86 +82,97 @@ final class BranchOptimizer {
case AND:
if (state) {
final Label skip = new Label("skip");
- branchOptimizer(lhs, skip, false);
- branchOptimizer(rhs, label, true);
+ optimizeLogicalOperand(lhs, skip, false, false);
+ optimizeLogicalOperand(rhs, label, true, true);
method.label(skip);
} else {
- branchOptimizer(lhs, label, false);
- branchOptimizer(rhs, label, false);
+ optimizeLogicalOperand(lhs, label, false, false);
+ optimizeLogicalOperand(rhs, label, false, true);
}
return;
case OR:
if (state) {
- branchOptimizer(lhs, label, true);
- branchOptimizer(rhs, label, true);
+ optimizeLogicalOperand(lhs, label, true, false);
+ optimizeLogicalOperand(rhs, label, true, true);
} else {
final Label skip = new Label("skip");
- branchOptimizer(lhs, skip, true);
- branchOptimizer(rhs, label, false);
+ optimizeLogicalOperand(lhs, skip, true, false);
+ optimizeLogicalOperand(rhs, label, false, true);
method.label(skip);
}
return;
case EQ:
case EQ_STRICT:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
+ codegen.loadBinaryOperands(binaryNode);
method.conditionalJump(state ? EQ : NE, true, label);
return;
case NE:
case NE_STRICT:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
+ codegen.loadBinaryOperands(binaryNode);
method.conditionalJump(state ? NE : EQ, true, label);
return;
case GE:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
- method.conditionalJump(state ? GE : LT, !state, label);
+ codegen.loadBinaryOperands(binaryNode);
+ method.conditionalJump(state ? GE : LT, false, label);
return;
case GT:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
- method.conditionalJump(state ? GT : LE, !state, label);
+ codegen.loadBinaryOperands(binaryNode);
+ method.conditionalJump(state ? GT : LE, false, label);
return;
case LE:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
- method.conditionalJump(state ? LE : GT, state, label);
+ codegen.loadBinaryOperands(binaryNode);
+ method.conditionalJump(state ? LE : GT, true, label);
return;
case LT:
- codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
- method.conditionalJump(state ? LT : GE, state, label);
+ codegen.loadBinaryOperands(binaryNode);
+ method.conditionalJump(state ? LT : GE, true, label);
return;
default:
break;
}
- codegen.load(binaryNode, Type.BOOLEAN);
- if (state) {
- method.ifne(label);
+ loadTestAndJump(binaryNode, label, state);
+ }
+
+ private void optimizeLogicalOperand(final Expression expr, final Label label, final boolean state, final boolean isRhs) {
+ final JoinPredecessorExpression jpexpr = (JoinPredecessorExpression)expr;
+ if(LocalVariableConversion.hasLiveConversion(jpexpr)) {
+ final Label after = new Label("after");
+ branchOptimizer(jpexpr.getExpression(), after, !state);
+ method.beforeJoinPoint(jpexpr);
+ method._goto(label);
+ method.label(after);
+ if(isRhs) {
+ method.beforeJoinPoint(jpexpr);
+ }
} else {
- method.ifeq(label);
+ branchOptimizer(jpexpr.getExpression(), label, state);
}
}
-
private void branchOptimizer(final Expression node, final Label label, final boolean state) {
- if (!(node instanceof TernaryNode)) {
-
- if (node instanceof BinaryNode) {
- branchOptimizer((BinaryNode)node, label, state);
- return;
- }
+ if (node instanceof BinaryNode) {
+ branchOptimizer((BinaryNode)node, label, state);
+ return;
+ }
- if (node instanceof UnaryNode) {
- branchOptimizer((UnaryNode)node, label, state);
- return;
- }
+ if (node instanceof UnaryNode) {
+ branchOptimizer((UnaryNode)node, label, state);
+ return;
}
- codegen.load(node, Type.BOOLEAN);
+ loadTestAndJump(node, label, state);
+ }
+
+ private void loadTestAndJump(final Expression node, final Label label, final boolean state) {
+ codegen.loadExpressionAsBoolean(node);
if (state) {
method.ifne(label);
} else {
diff --git a/src/jdk/nashorn/internal/codegen/ClassEmitter.java b/src/jdk/nashorn/internal/codegen/ClassEmitter.java
index 09c6a065..80bb61dd 100644
--- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java
+++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java
@@ -49,25 +49,27 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
import static jdk.nashorn.internal.codegen.CompilerConstants.className;
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
-import java.util.Arrays;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.debug.NashornClassReader;
+import jdk.nashorn.internal.ir.debug.NashornTextifier;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.RewriteException;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.Source;
@@ -106,6 +108,8 @@ import jdk.nashorn.internal.runtime.Source;
* @see Compiler
*/
public class ClassEmitter implements Emitter {
+ /** Default flags for class generation - public class */
+ private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC);
/** Sanity check flag - have we started on a class? */
private boolean classStarted;
@@ -123,10 +127,7 @@ public class ClassEmitter implements Emitter {
protected final ClassWriter cw;
/** The script environment */
- protected final ScriptEnvironment env;
-
- /** Default flags for class generation - oublic class */
- private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC);
+ protected final Context context;
/** Compile unit class name. */
private String unitClassName;
@@ -134,6 +135,16 @@ public class ClassEmitter implements Emitter {
/** Set of constants access methods required. */
private Set<Class<?>> constantMethodNeeded;
+ private int methodCount;
+
+ private int initCount;
+
+ private int clinitCount;
+
+ private int fieldCount;
+
+ private final Set<String> methodNames;
+
/**
* Constructor - only used internally in this class as it breaks
* abstraction towards ASM or other code generator below
@@ -141,12 +152,19 @@ public class ClassEmitter implements Emitter {
* @param env script environment
* @param cw ASM classwriter
*/
- private ClassEmitter(final ScriptEnvironment env, final ClassWriter cw) {
- assert env != null;
-
- this.env = env;
+ private ClassEmitter(final Context context, final ClassWriter cw) {
+ this.context = context;
this.cw = cw;
this.methodsStarted = new HashSet<>();
+ this.methodNames = new HashSet<>();
+ }
+
+ /**
+ * Return the method names encountered
+ * @return method names
+ */
+ public Set<String> getMethodNames() {
+ return Collections.unmodifiableSet(methodNames);
}
/**
@@ -157,8 +175,8 @@ public class ClassEmitter implements Emitter {
* @param superClassName super class name for class
* @param interfaceNames names of interfaces implemented by this class, or null if none
*/
- ClassEmitter(final ScriptEnvironment env, final String className, final String superClassName, final String... interfaceNames) {
- this(env, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
+ ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) {
+ this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames);
}
@@ -170,8 +188,8 @@ public class ClassEmitter implements Emitter {
* @param unitClassName Compile unit class name.
* @param strictMode Should we generate this method in strict mode
*/
- ClassEmitter(final ScriptEnvironment env, final String sourceName, final String unitClassName, final boolean strictMode) {
- this(env,
+ ClassEmitter(final Context context, final String sourceName, final String unitClassName, final boolean strictMode) {
+ this(context,
new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
private static final String OBJECT_CLASS = "java/lang/Object";
@@ -197,6 +215,10 @@ public class ClassEmitter implements Emitter {
defineCommonStatics(strictMode);
}
+ Context getContext() {
+ return context;
+ }
+
/**
* Returns the name of the compile unit class name.
* @return the name of the compile unit class name.
@@ -206,6 +228,38 @@ public class ClassEmitter implements Emitter {
}
/**
+ * Get the method count, including init and clinit methods
+ * @return method count
+ */
+ public int getMethodCount() {
+ return methodCount;
+ }
+
+ /**
+ * Get the clinit count
+ * @return clinit count
+ */
+ public int getClinitCount() {
+ return clinitCount;
+ }
+
+ /**
+ * Get the init count
+ * @return init count
+ */
+ public int getInitCount() {
+ return initCount;
+ }
+
+ /**
+ * Get the field count
+ * @return field count
+ */
+ public int getFieldCount() {
+ return fieldCount;
+ }
+
+ /**
* Convert a binary name to a package/class name.
*
* @param name Binary name.
@@ -274,51 +328,51 @@ public class ClassEmitter implements Emitter {
}
// $getXXXX$array - get the ith entry from the constants table and cast to XXXX[].
- for (final Class<?> cls : constantMethodNeeded) {
- if (cls.isArray()) {
- defineGetArrayMethod(cls);
+ for (final Class<?> clazz : constantMethodNeeded) {
+ if (clazz.isArray()) {
+ defineGetArrayMethod(clazz);
}
}
}
/**
- * Constructs a primitive specific method for getting the ith entry from the constants table and cast.
- * @param cls Array class.
+ * Constructs a primitive specific method for getting the ith entry from the constants table as an array.
+ * @param clazz Array class.
*/
- private void defineGetArrayMethod(final Class<?> cls) {
+ private void defineGetArrayMethod(final Class<?> clazz) {
assert unitClassName != null;
- final String methodName = getArrayMethodName(cls);
- final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, cls, int.class);
+ final String methodName = getArrayMethodName(clazz);
+ final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, clazz, int.class);
getArrayMethod.begin();
getArrayMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor())
.load(Type.INT, 0)
.arrayload()
- .checkcast(cls)
- .dup()
- .arraylength()
- .invoke(staticCallNoLookup(Arrays.class, "copyOf", cls, cls, int.class))
+ .checkcast(clazz)
+ .invoke(virtualCallNoLookup(clazz, "clone", Object.class))
+ .checkcast(clazz)
._return();
getArrayMethod.end();
}
+
/**
* Generate the name of a get array from constant pool method.
- * @param cls Name of array class.
+ * @param clazz Name of array class.
* @return Method name.
*/
- static String getArrayMethodName(final Class<?> cls) {
- assert cls.isArray();
- return GET_ARRAY_PREFIX.symbolName() + cls.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName();
+ static String getArrayMethodName(final Class<?> clazz) {
+ assert clazz.isArray();
+ return GET_ARRAY_PREFIX.symbolName() + clazz.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName();
}
/**
* Ensure a get constant method is issued for the class.
- * @param cls Class of constant.
+ * @param clazz Class of constant.
*/
- void needGetConstantMethod(final Class<?> cls) {
- constantMethodNeeded.add(cls);
+ void needGetConstantMethod(final Class<?> clazz) {
+ constantMethodNeeded.add(clazz);
}
/**
@@ -356,9 +410,16 @@ public class ClassEmitter implements Emitter {
*/
@Override
public void end() {
- assert classStarted;
+ assert classStarted : "class not started for " + unitClassName;
if (unitClassName != null) {
+ final MethodEmitter initMethod = init(EnumSet.of(Flag.PRIVATE));
+ initMethod.begin();
+ initMethod.load(Type.OBJECT, 0);
+ initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
+ initMethod.returnVoid();
+ initMethod.end();
+
defineCommonUtilities();
}
@@ -376,16 +437,19 @@ public class ClassEmitter implements Emitter {
static String disassemble(final byte[] bytecode) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (final PrintWriter pw = new PrintWriter(baos)) {
- new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0);
+ final NashornClassReader cr = new NashornClassReader(bytecode);
+ final Context ctx = AccessController.doPrivileged(new PrivilegedAction<Context>() {
+ @Override
+ public Context run() {
+ return Context.getContext();
+ }
+ });
+ final TraceClassVisitor tcv = new TraceClassVisitor(null, new NashornTextifier(ctx.getEnv(), cr), pw);
+ cr.accept(tcv, 0);
}
- return new String(baos.toByteArray());
- }
- /**
- * @return env used for class emission
- */
- ScriptEnvironment getEnv() {
- return env;
+ final String str = new String(baos.toByteArray());
+ return str;
}
/**
@@ -412,10 +476,6 @@ public class ClassEmitter implements Emitter {
methodsStarted.remove(method);
}
- SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
- return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode);
- }
-
/**
* Add a new method to the class - defaults to public method
*
@@ -440,6 +500,8 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving this method
*/
MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+ methodCount++;
+ methodNames.add(methodName);
return new MethodEmitter(this, methodVisitor(methodFlags, methodName, rtype, ptypes));
}
@@ -465,6 +527,8 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving this method
*/
MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) {
+ methodCount++;
+ methodNames.add(methodName);
return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null));
}
@@ -475,10 +539,13 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving this method
*/
MethodEmitter method(final FunctionNode functionNode) {
+ methodCount++;
+ methodNames.add(functionNode.getName());
+ final FunctionSignature signature = new FunctionSignature(functionNode);
final MethodVisitor mv = cw.visitMethod(
ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0),
functionNode.getName(),
- new FunctionSignature(functionNode).toString(),
+ signature.toString(),
null,
null);
@@ -486,11 +553,32 @@ public class ClassEmitter implements Emitter {
}
/**
+ * Add a new method to the class, representing a rest-of version of the function node
+ *
+ * @param functionNode the function node to generate a method for
+ * @return method emitter to use for weaving this method
+ */
+ MethodEmitter restOfMethod(final FunctionNode functionNode) {
+ methodCount++;
+ methodNames.add(functionNode.getName());
+ final MethodVisitor mv = cw.visitMethod(
+ ACC_PUBLIC | ACC_STATIC,
+ functionNode.getName(),
+ Type.getMethodDescriptor(functionNode.getReturnType().getTypeClass(), RewriteException.class),
+ null,
+ null);
+
+ return new MethodEmitter(this, mv, functionNode);
+ }
+
+
+ /**
* Start generating the <clinit> method in the class
*
* @return method emitter to use for weaving <clinit>
*/
MethodEmitter clinit() {
+ clinitCount++;
return method(EnumSet.of(Flag.STATIC), CLINIT.symbolName(), void.class);
}
@@ -500,6 +588,7 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving <init>()V
*/
MethodEmitter init() {
+ initCount++;
return method(INIT.symbolName(), void.class);
}
@@ -510,6 +599,7 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving <init>()V
*/
MethodEmitter init(final Class<?>... ptypes) {
+ initCount++;
return method(INIT.symbolName(), void.class, ptypes);
}
@@ -522,6 +612,7 @@ public class ClassEmitter implements Emitter {
* @return method emitter to use for weaving <init>(...)V
*/
MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) {
+ initCount++;
return method(flags, INIT.symbolName(), void.class, ptypes);
}
@@ -536,6 +627,7 @@ public class ClassEmitter implements Emitter {
* @see ClassEmitter.Flag
*/
final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) {
+ fieldCount++;
cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd();
}
@@ -636,7 +728,7 @@ public class ClassEmitter implements Emitter {
}
}
- private MethodVisitor methodVisitor(EnumSet<Flag> flags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+ private MethodVisitor methodVisitor(final EnumSet<Flag> flags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
return cw.visitMethod(Flag.getValue(flags), methodName, methodDescriptor(rtype, ptypes), null, null);
}
diff --git a/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index 52bdc7cb..59aa258e 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -29,13 +29,12 @@ import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE;
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC;
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP;
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.REGEX_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_ARRAY_ARG;
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
@@ -45,25 +44,40 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT;
import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_TEMP;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;
-import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
import java.io.PrintWriter;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.function.Supplier;
+import jdk.nashorn.internal.AssertsEnabled;
+import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.AccessNode;
@@ -83,22 +97,30 @@ import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.GetSplitState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
+import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.LoopNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.Optimistic;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.ReturnNode;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.SetSplitState;
+import jdk.nashorn.internal.ir.SplitReturn;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.Symbol;
@@ -117,20 +139,26 @@ import jdk.nashorn.internal.parser.Lexer.RegexToken;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.RewriteException;
import jdk.nashorn.internal.runtime.Scope;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* This is the lowest tier of the code generator. It takes lowered ASTs emitted
@@ -151,16 +179,44 @@ import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
* The CodeGenerator visits nodes only once, tags them as resolved and emits
* bytecode for them.
*/
-final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> {
+@Logger(name="codegen")
+final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
+
+ private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);
- private static final String SCRIPTFUNCTION_IMPL_OBJECT = Type.getInternalName(ScriptFunctionImpl.class);
+ private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class);
+ private static final Type SCRIPTFUNCTION_IMPL_TYPE = Type.typeFor(ScriptFunction.class);
+
+ private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
+ "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
+ private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
+ "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);
+
+ private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+ "ensureInt", int.class, Object.class, int.class);
+ private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+ "ensureLong", long.class, Object.class, int.class);
+ private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+ "ensureNumber", double.class, Object.class, int.class);
+
+ private static final Class<?> ITERATOR_CLASS = Iterator.class;
+ static {
+ assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
+ }
+ private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
+ private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
+
+ private static final Integer INT_ZERO = Integer.valueOf(0);
/** Constant data & installation. The only reason the compiler keeps this is because it is assigned
* by reflection in class installation */
private final Compiler compiler;
+ /** Is the current code submitted by 'eval' call? */
+ private final boolean evalCode;
+
/** Call site flags given to the code generator to be used for all generated call sites */
private final int callSiteFlags;
@@ -180,22 +236,48 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
/** Current compile unit */
private CompileUnit unit;
- private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug");
+ private final DebugLogger log;
/** From what size should we use spill instead of fields for JavaScript objects? */
- private static final int OBJECT_SPILL_THRESHOLD = 300;
+ private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
private final Set<String> emittedMethods = new HashSet<>();
+ // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
+ private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>();
+
+ private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
+
+ private static final Label METHOD_BOUNDARY = new Label("");
+ private final Deque<Label> catchLabels = new ArrayDeque<>();
+ // Number of live locals on entry to (and thus also break from) labeled blocks.
+ private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
+
+ //is this a rest of compilation
+ private final int[] continuationEntryPoints;
+
/**
* Constructor.
*
* @param compiler
*/
- CodeGenerator(final Compiler compiler) {
+ CodeGenerator(final Compiler compiler, final int[] continuationEntryPoints) {
super(new CodeGeneratorLexicalContext());
- this.compiler = compiler;
- this.callSiteFlags = compiler.getEnv()._callsite_flags;
+ this.compiler = compiler;
+ this.evalCode = compiler.getSource().isEvalCode();
+ this.continuationEntryPoints = continuationEntryPoints;
+ this.callSiteFlags = compiler.getScriptEnvironment()._callsite_flags;
+ this.log = initLogger(compiler.getContext());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
}
/**
@@ -205,7 +287,15 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* @return the correct flags for a call site in the current function
*/
int getCallSiteFlags() {
- return lc.getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
+ return lc.getCurrentFunction().getCallSiteFlags() | callSiteFlags;
+ }
+
+ /**
+ * Are we generating code for 'eval' code?
+ * @return true if currently compiled code is 'eval' code.
+ */
+ boolean isEvalCode() {
+ return evalCode;
}
/**
@@ -214,38 +304,79 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* @param identNode an identity node to load
* @return the method generator used
*/
- private MethodEmitter loadIdent(final IdentNode identNode, final Type type) {
+ private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) {
+ checkTemporalDeadZone(identNode);
final Symbol symbol = identNode.getSymbol();
if (!symbol.isScope()) {
+ final Type type = identNode.getType();
+ if(type == Type.UNDEFINED) {
+ return method.loadUndefined(resultBounds.widest);
+ }
+
assert symbol.hasSlot() || symbol.isParam();
- return method.load(symbol).convert(type);
+ return method.load(identNode);
}
- final String name = symbol.getName();
- final Source source = lc.getCurrentFunction().getSource();
-
- if (CompilerConstants.__FILE__.name().equals(name)) {
- return method.load(source.getName());
- } else if (CompilerConstants.__DIR__.name().equals(name)) {
- return method.load(source.getBase());
- } else if (CompilerConstants.__LINE__.name().equals(name)) {
- return method.load(source.getLine(identNode.position())).convert(Type.OBJECT);
+ assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
+ final int flags = CALLSITE_SCOPE | getCallSiteFlags();
+ if (isFastScope(symbol)) {
+ // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
+ if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
+ method.loadCompilerConstant(SCOPE);
+ // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
+ // just a single definitive type, resultBounds.widest.
+ loadSharedScopeVar(resultBounds.widest, symbol, flags);
+ } else {
+ new LoadFastScopeVar(identNode, resultBounds, flags).emit();
+ }
} else {
- assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
+ //slow scope load, we have no proto depth
+ new LoadScopeVar(identNode, resultBounds, flags).emit();
+ }
- final int flags = CALLSITE_SCOPE | getCallSiteFlags();
- method.loadCompilerConstant(SCOPE);
+ return method;
+ }
+
+ // Any access to LET and CONST variables before their declaration must throw ReferenceError.
+ // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
+ private void checkTemporalDeadZone(final IdentNode identNode) {
+ if (identNode.isDead()) {
+ method.load(identNode.getSymbol().getName());
+ method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+ }
+ }
- if (isFastScope(symbol)) {
- // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
- if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD) {
- return loadSharedScopeVar(type, symbol, flags);
+ private boolean isRestOf() {
+ return continuationEntryPoints != null;
+ }
+
+ private boolean isOptimisticOrRestOf() {
+ return useOptimisticTypes() || isRestOf();
+ }
+
+ private boolean isCurrentContinuationEntryPoint(final int programPoint) {
+ return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
+ }
+
+ private int[] getContinuationEntryPoints() {
+ return isRestOf() ? continuationEntryPoints : null;
+ }
+
+ private int getCurrentContinuationEntryPoint() {
+ return isRestOf() ? continuationEntryPoints[0] : INVALID_PROGRAM_POINT;
+ }
+
+ private boolean isContinuationEntryPoint(final int programPoint) {
+ if (isRestOf()) {
+ assert continuationEntryPoints != null;
+ for (final int cep : continuationEntryPoints) {
+ if (cep == programPoint) {
+ return true;
}
- return loadFastScopeVar(type, symbol, flags, identNode.isFunction());
}
- return method.dynamicGet(type, identNode.getName(), flags, identNode.isFunction());
}
+ return false;
}
/**
@@ -285,7 +416,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
previousWasBlock = true;
} else {
- if ((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && CodeGeneratorLexicalContext.isFunctionDynamicScope((FunctionNode)node))) {
+ if (node instanceof WithNode && previousWasBlock || node instanceof FunctionNode && ((FunctionNode)node).needsDynamicScope()) {
// If we hit a scope that can have symbols introduced into it at run time before finding the defining
// block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
// before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
@@ -300,40 +431,89 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
- method.load(isFastScope(symbol) ? getScopeProtoDepth(lc.getCurrentBlock(), symbol) : -1);
- final SharedScopeCall scopeCall = lc.getScopeGet(unit, valueType, symbol, flags | CALLSITE_FAST_SCOPE);
- return scopeCall.generateInvoke(method);
+ assert !isOptimisticOrRestOf();
+ if (isFastScope(symbol)) {
+ method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
+ } else {
+ method.load(-1);
+ }
+ return lc.getScopeGet(unit, symbol, valueType, flags | CALLSITE_FAST_SCOPE).generateInvoke(method);
}
- private MethodEmitter loadFastScopeVar(final Type valueType, final Symbol symbol, final int flags, final boolean isMethod) {
- loadFastScopeProto(symbol, false);
- return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
+ private class LoadScopeVar extends OptimisticOperation {
+ final IdentNode identNode;
+ private final int flags;
+
+ LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
+ super(identNode, resultBounds);
+ this.identNode = identNode;
+ this.flags = flags;
+ }
+
+ @Override
+ void loadStack() {
+ method.loadCompilerConstant(SCOPE);
+ getProto();
+ }
+
+ void getProto() {
+ //empty
+ }
+
+ @Override
+ void consumeStack() {
+ // If this is either __FILE__, __DIR__, or __LINE__ then load the property initially as Object as we'd convert
+ // it anyway for replaceLocationPropertyPlaceholder.
+ if(identNode.isCompileTimePropertyName()) {
+ method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
+ replaceCompileTimeProperty();
+ } else {
+ dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
+ }
+ }
+ }
+
+ private class LoadFastScopeVar extends LoadScopeVar {
+ LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
+ super(identNode, resultBounds, flags | CALLSITE_FAST_SCOPE);
+ }
+
+ @Override
+ void getProto() {
+ loadFastScopeProto(identNode.getSymbol(), false);
+ }
}
private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
loadFastScopeProto(symbol, true);
- method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE);
+ method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE, false);
return method;
}
private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
+ //walk up the chain from starting block and when we bump into the current function boundary, add the external
+ //information.
+ final FunctionNode fn = lc.getCurrentFunction();
+ final int externalDepth = compiler.getScriptFunctionData(fn.getId()).getExternalSymbolDepth(symbol.getName());
+
+ //count the number of scopes from this place to the start of the function
+
+ final int internalDepth = FindScopeDepths.findInternalDepth(lc, fn, startingBlock, symbol);
+ final int scopesToStart = FindScopeDepths.findScopesToStart(lc, fn, startingBlock);
int depth = 0;
- final String name = symbol.getName();
- for(final Iterator<Block> blocks = lc.getBlocks(startingBlock); blocks.hasNext();) {
- final Block currentBlock = blocks.next();
- if (currentBlock.getExistingSymbol(name) == symbol) {
- return depth;
- }
- if (currentBlock.needsScope()) {
- ++depth;
- }
+ if (internalDepth == -1) {
+ depth = scopesToStart + externalDepth;
+ } else {
+ assert internalDepth <= scopesToStart;
+ depth = internalDepth;
}
- return -1;
+
+ return depth;
}
private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
- assert depth != -1;
+ assert depth != -1 : "Couldn't find scope depth for symbol " + symbol.getName() + " in " + lc.getCurrentFunction();
if (depth > 0) {
if (swap) {
method.swap();
@@ -348,29 +528,36 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
/**
- * Generate code that loads this node to the stack. This method is only
- * public to be accessible from the maps sub package. Do not call externally
+ * Generate code that loads this node to the stack, not constraining its type
*
- * @param node node to load
+ * @param expr node to load
*
* @return the method emitter used
*/
- MethodEmitter load(final Expression node) {
- return load(node, node.hasType() ? node.getType() : null, false);
+ private MethodEmitter loadExpressionUnbounded(final Expression expr) {
+ return loadExpression(expr, TypeBounds.UNBOUNDED);
+ }
+
+ private MethodEmitter loadExpressionAsObject(final Expression expr) {
+ return loadExpression(expr, TypeBounds.OBJECT);
+ }
+
+ MethodEmitter loadExpressionAsBoolean(final Expression expr) {
+ return loadExpression(expr, TypeBounds.BOOLEAN);
}
// Test whether conversion from source to target involves a call of ES 9.1 ToPrimitive
// with possible side effects from calling an object's toString or valueOf methods.
- private boolean noToPrimitiveConversion(final Type source, final Type target) {
+ private static boolean noToPrimitiveConversion(final Type source, final Type target) {
// Object to boolean conversion does not cause ToPrimitive call
return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
}
- MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type) {
- return loadBinaryOperands(lhs, rhs, type, false);
+ MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
+ return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
}
- private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type, final boolean baseAlreadyOnStack) {
+ private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack, final boolean forceConversionSeparation) {
// ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
// expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
// RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
@@ -381,38 +568,154 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// a primitive value, or RIGHT is an expression that loads without side effects, then we can do the
// reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly
// separate operations to preserve specification semantics.
- if (noToPrimitiveConversion(lhs.getType(), type) || rhs.isLocal()) {
- // Can reorder. Combine load and convert into single operations.
- load(lhs, type, baseAlreadyOnStack);
- load(rhs, type, false);
+
+ // Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
+ // than the lower explicit bound, but it should also not be wider than
+ final Type lhsType = undefinedToNumber(lhs.getType());
+ final Type rhsType = undefinedToNumber(rhs.getType());
+ final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
+ final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
+ if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
+ // Can reorder. We might still need to separate conversion, but at least we can do it with reordering
+ if (forceConversionSeparation) {
+ // Can reorder, but can't move conversion into the operand as the operation depends on operands
+ // exact types for its overflow guarantees. E.g. with {L}{%I}expr1 {L}* {L}{%I}expr2 we are not allowed
+ // to merge {L}{%I} into {%L}, as that can cause subsequent overflows; test for JDK-8058610 contains
+ // concrete cases where this could happen.
+ final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
+ loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
+ method.convert(operandBounds.within(method.peekType()));
+ loadExpression(rhs, safeConvertBounds, false);
+ method.convert(operandBounds.within(method.peekType()));
+ } else {
+ // Can reorder and move conversion into the operand. Combine load and convert into single operations.
+ loadExpression(lhs, operandBounds, baseAlreadyOnStack);
+ loadExpression(rhs, operandBounds, false);
+ }
} else {
// Can't reorder. Load and convert separately.
- load(lhs, lhs.getType(), baseAlreadyOnStack);
- load(rhs, rhs.getType(), false);
- method.swap().convert(type).swap().convert(type);
+ final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
+ loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
+ final Type lhsLoadedType = method.peekType();
+ loadExpression(rhs, safeConvertBounds, false);
+ final Type convertedLhsType = operandBounds.within(method.peekType());
+ if (convertedLhsType != lhsLoadedType) {
+ // Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
+ method.swap().convert(convertedLhsType).swap();
+ }
+ method.convert(operandBounds.within(method.peekType()));
}
+ assert Type.generic(method.peekType()) == operandBounds.narrowest;
+ assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
return method;
}
- MethodEmitter loadBinaryOperands(final BinaryNode node) {
- return loadBinaryOperands(node.lhs(), node.rhs(), node.getType(), false);
+ private static final Type undefinedToNumber(final Type type) {
+ return type == Type.UNDEFINED ? Type.NUMBER : type;
}
- MethodEmitter load(final Expression node, final Type type) {
- return load(node, type, false);
+ private static final class TypeBounds {
+ final Type narrowest;
+ final Type widest;
+
+ static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
+ static final TypeBounds INT = exact(Type.INT);
+ static final TypeBounds OBJECT = exact(Type.OBJECT);
+ static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
+
+ static TypeBounds exact(final Type type) {
+ return new TypeBounds(type, type);
+ }
+
+ TypeBounds(final Type narrowest, final Type widest) {
+ assert widest != null && widest != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
+ assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
+ assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
+ assert !widest.narrowerThan(narrowest);
+ this.narrowest = Type.generic(narrowest);
+ this.widest = Type.generic(widest);
+ }
+
+ TypeBounds notNarrowerThan(final Type type) {
+ return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
+ }
+
+ TypeBounds notWiderThan(final Type type) {
+ return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
+ }
+
+ boolean canBeNarrowerThan(final Type type) {
+ return narrowest.narrowerThan(type);
+ }
+
+ TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
+ if(newNarrowest == narrowest && newWidest == widest) {
+ return this;
+ }
+ return new TypeBounds(newNarrowest, newWidest);
+ }
+
+ TypeBounds booleanToInt() {
+ return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
+ }
+
+ TypeBounds objectToNumber() {
+ return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
+ }
+
+ Type within(final Type type) {
+ if(type.narrowerThan(narrowest)) {
+ return narrowest;
+ }
+ if(type.widerThan(widest)) {
+ return widest;
+ }
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + narrowest + ", " + widest + "]";
+ }
}
- private MethodEmitter load(final Expression node, final Type type, final boolean baseAlreadyOnStack) {
- final Symbol symbol = node.getSymbol();
+ private static Type booleanToInt(final Type t) {
+ return t == Type.BOOLEAN ? Type.INT : t;
+ }
- // If we lack symbols, we just generate what we see.
- if (symbol == null || type == null) {
- node.accept(this);
- return method;
+ private static Type objectToNumber(final Type t) {
+ return t.isObject() ? Type.NUMBER : t;
+ }
+
+ MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
+ if(type == Type.BOOLEAN) {
+ return loadExpressionAsBoolean(expr);
+ } else if(type == Type.UNDEFINED) {
+ assert expr.getType() == Type.UNDEFINED;
+ return loadExpressionAsObject(expr);
}
+ // having no upper bound preserves semantics of optimistic operations in the expression (by not having them
+ // converted early) and then applies explicit conversion afterwards.
+ return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
+ }
+
+ private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
+ return loadExpression(expr, resultBounds, false);
+ }
- assert !type.isUnknown();
+ /**
+ * Emits code for evaluating an expression and leaving its value on top of the stack, narrowing or widening it if
+ * necessary.
+ * @param expr the expression to load
+ * @param resultBounds the incoming type bounds. The value on the top of the stack is guaranteed to not be of narrower
+ * type than the narrowest bound, or wider type than the widest bound after it is loaded.
+ * @param baseAlreadyOnStack true if the base of an access or index node is already on the stack. Used to avoid
+ * double evaluation of bases in self-assignment expressions to access and index nodes. {@code Type.OBJECT} is used
+ * to indicate the widest possible type.
+ * @return the method emitter
+ */
+ private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds, final boolean baseAlreadyOnStack) {
/*
* The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
@@ -421,35 +724,54 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
*/
final CodeGenerator codegen = this;
- node.accept(new NodeVisitor<LexicalContext>(lc) {
+ final Node currentDiscard = codegen.lc.getCurrentDiscard();
+ expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterIdentNode(final IdentNode identNode) {
- loadIdent(identNode, type);
+ loadIdent(identNode, resultBounds);
return false;
}
@Override
public boolean enterAccessNode(final AccessNode accessNode) {
- if (!baseAlreadyOnStack) {
- load(accessNode.getBase(), Type.OBJECT);
- }
- assert method.peekType().isObject();
- method.dynamicGet(type, accessNode.getProperty().getName(), getCallSiteFlags(), accessNode.isFunction());
+ new OptimisticOperation(accessNode, resultBounds) {
+ @Override
+ void loadStack() {
+ if (!baseAlreadyOnStack) {
+ loadExpressionAsObject(accessNode.getBase());
+ }
+ assert method.peekType().isObject();
+ }
+ @Override
+ void consumeStack() {
+ final int flags = getCallSiteFlags();
+ dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
+ }
+ }.emit(baseAlreadyOnStack ? 1 : 0);
return false;
}
@Override
public boolean enterIndexNode(final IndexNode indexNode) {
- if (!baseAlreadyOnStack) {
- load(indexNode.getBase(), Type.OBJECT);
- load(indexNode.getIndex());
- }
- method.dynamicGetIndex(type, getCallSiteFlags(), indexNode.isFunction());
+ new OptimisticOperation(indexNode, resultBounds) {
+ @Override
+ void loadStack() {
+ if (!baseAlreadyOnStack) {
+ loadExpressionAsObject(indexNode.getBase());
+ loadExpressionUnbounded(indexNode.getIndex());
+ }
+ }
+ @Override
+ void consumeStack() {
+ final int flags = getCallSiteFlags();
+ dynamicGetIndex(flags, indexNode.isFunction());
+ }
+ }.emit(baseAlreadyOnStack ? 2 : 0);
return false;
}
@Override
- public boolean enterFunctionNode(FunctionNode functionNode) {
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
// function nodes will always leave a constructed function object on stack, no need to load the symbol
// separately as in enterDefault()
lc.pop(functionNode);
@@ -459,204 +781,496 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
// re-push the original functionNode.
lc.push(functionNode);
- method.convert(type);
return false;
}
@Override
- public boolean enterCallNode(CallNode callNode) {
- return codegen.enterCallNode(callNode, type);
+ public boolean enterASSIGN(final BinaryNode binaryNode) {
+ loadASSIGN(binaryNode);
+ return false;
}
@Override
- public boolean enterLiteralNode(LiteralNode<?> literalNode) {
- return codegen.enterLiteralNode(literalNode, type);
+ public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
+ loadASSIGN_ADD(binaryNode);
+ return false;
}
@Override
- public boolean enterDefault(final Node otherNode) {
- final Node currentDiscard = codegen.lc.getCurrentDiscard();
- otherNode.accept(codegen); // generate code for whatever we are looking at.
- if(currentDiscard != otherNode) {
- method.load(symbol); // load the final symbol to the stack (or nop if no slot, then result is already there)
- assert method.peekType() != null;
- method.convert(type);
- }
+ public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
+ loadASSIGN_BIT_AND(binaryNode);
return false;
}
- });
- return method;
- }
+ @Override
+ public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
+ loadASSIGN_BIT_OR(binaryNode);
+ return false;
+ }
- @Override
- public boolean enterAccessNode(final AccessNode accessNode) {
- load(accessNode);
- return false;
- }
+ @Override
+ public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+ loadASSIGN_BIT_XOR(binaryNode);
+ return false;
+ }
- /**
- * Initialize a specific set of vars to undefined. This has to be done at
- * the start of each method for local variables that aren't passed as
- * parameters.
- *
- * @param symbols list of symbols.
- */
- private void initSymbols(final Iterable<Symbol> symbols) {
- final LinkedList<Symbol> numbers = new LinkedList<>();
- final LinkedList<Symbol> objects = new LinkedList<>();
+ @Override
+ public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
+ loadASSIGN_DIV(binaryNode);
+ return false;
+ }
- for (final Symbol symbol : symbols) {
- /*
- * The following symbols are guaranteed to be defined and thus safe
- * from having undefined written to them: parameters internals this
- *
- * Otherwise we must, unless we perform control/escape analysis,
- * assign them undefined.
- */
- final boolean isInternal = symbol.isParam() || symbol.isInternal() || symbol.isThis() || !symbol.canBeUndefined();
-
- if (symbol.hasSlot() && !isInternal) {
- assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + lc.getCurrentFunction();
- if (symbol.getSymbolType().isNumber()) {
- numbers.add(symbol);
- } else if (symbol.getSymbolType().isObject()) {
- objects.add(symbol);
- }
+ @Override
+ public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
+ loadASSIGN_MOD(binaryNode);
+ return false;
}
- }
- initSymbols(numbers, Type.NUMBER);
- initSymbols(objects, Type.OBJECT);
- }
+ @Override
+ public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
+ loadASSIGN_MUL(binaryNode);
+ return false;
+ }
- private void initSymbols(final LinkedList<Symbol> symbols, final Type type) {
- final Iterator<Symbol> it = symbols.iterator();
- if(it.hasNext()) {
- method.loadUndefined(type);
- boolean hasNext;
- do {
- final Symbol symbol = it.next();
- hasNext = it.hasNext();
- if(hasNext) {
- method.dup();
- }
- method.store(symbol);
- } while(hasNext);
+ @Override
+ public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
+ loadASSIGN_SAR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
+ loadASSIGN_SHL(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
+ loadASSIGN_SHR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
+ loadASSIGN_SUB(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ return loadCallNode(callNode, resultBounds);
+ }
+
+ @Override
+ public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+ loadLiteral(literalNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+ loadTernaryNode(ternaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterADD(final BinaryNode binaryNode) {
+ loadADD(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterSUB(final UnaryNode unaryNode) {
+ loadSUB(unaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterSUB(final BinaryNode binaryNode) {
+ loadSUB(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterMUL(final BinaryNode binaryNode) {
+ loadMUL(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterDIV(final BinaryNode binaryNode) {
+ loadDIV(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterMOD(final BinaryNode binaryNode) {
+ loadMOD(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterSAR(final BinaryNode binaryNode) {
+ loadSAR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterSHL(final BinaryNode binaryNode) {
+ loadSHL(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterSHR(final BinaryNode binaryNode) {
+ loadSHR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
+ loadCOMMALEFT(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
+ loadCOMMARIGHT(binaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterAND(final BinaryNode binaryNode) {
+ loadAND_OR(binaryNode, resultBounds, true);
+ return false;
+ }
+
+ @Override
+ public boolean enterOR(final BinaryNode binaryNode) {
+ loadAND_OR(binaryNode, resultBounds, false);
+ return false;
+ }
+
+ @Override
+ public boolean enterNOT(final UnaryNode unaryNode) {
+ loadNOT(unaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterADD(final UnaryNode unaryNode) {
+ loadADD(unaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterBIT_NOT(final UnaryNode unaryNode) {
+ loadBIT_NOT(unaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterBIT_AND(final BinaryNode binaryNode) {
+ loadBIT_AND(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterBIT_OR(final BinaryNode binaryNode) {
+ loadBIT_OR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterBIT_XOR(final BinaryNode binaryNode) {
+ loadBIT_XOR(binaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterVOID(final UnaryNode unaryNode) {
+ loadVOID(unaryNode, resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterEQ(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.EQ);
+ return false;
+ }
+
+ @Override
+ public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.EQ);
+ return false;
+ }
+
+ @Override
+ public boolean enterGE(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.GE);
+ return false;
+ }
+
+ @Override
+ public boolean enterGT(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.GT);
+ return false;
+ }
+
+ @Override
+ public boolean enterLE(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.LE);
+ return false;
+ }
+
+ @Override
+ public boolean enterLT(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.LT);
+ return false;
+ }
+
+ @Override
+ public boolean enterNE(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.NE);
+ return false;
+ }
+
+ @Override
+ public boolean enterNE_STRICT(final BinaryNode binaryNode) {
+ loadCmp(binaryNode, Condition.NE);
+ return false;
+ }
+
+ @Override
+ public boolean enterObjectNode(final ObjectNode objectNode) {
+ loadObjectNode(objectNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
+ loadRuntimeNode(runtimeNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterNEW(final UnaryNode unaryNode) {
+ loadNEW(unaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterDECINC(final UnaryNode unaryNode) {
+ loadDECINC(unaryNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
+ loadExpression(joinExpr.getExpression(), resultBounds);
+ return false;
+ }
+
+ @Override
+ public boolean enterGetSplitState(final GetSplitState getSplitState) {
+ method.loadScope();
+ method.invoke(Scope.GET_SPLIT_STATE);
+ return false;
+ }
+
+ @Override
+ public boolean enterDefault(final Node otherNode) {
+ // Must have handled all expressions that can legally be encountered.
+ throw new AssertionError(otherNode.getClass().getName());
+ }
+ });
+ if(currentDiscard != expr) {
+ coerceStackTop(resultBounds);
}
+ return method;
+ }
+
+ private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
+ return method.convert(typeBounds.within(method.peekType()));
}
/**
- * Create symbol debug information.
+ * Closes any still open entries for this block's local variables in the bytecode local variable table.
*
* @param block block containing symbols.
*/
- private void symbolInfo(final Block block) {
+ private void closeBlockVariables(final Block block) {
for (final Symbol symbol : block.getSymbols()) {
- if (symbol.hasSlot()) {
- method.localVariable(symbol, block.getEntryLabel(), block.getBreakLabel());
+ if (symbol.isBytecodeLocal()) {
+ method.closeLocalVariable(symbol, block.getBreakLabel());
}
}
}
@Override
public boolean enterBlock(final Block block) {
+ method.label(block.getEntryLabel());
+ if(!method.isReachable()) {
+ return false;
+ }
if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
return false;
}
- method.label(block.getEntryLabel());
initLocals(block);
+ assert lc.getUsedSlotCount() == method.getFirstTemp();
return true;
}
+ private boolean useOptimisticTypes() {
+ return !lc.inSplitNode() && compiler.useOptimisticTypes();
+ }
+
@Override
public Node leaveBlock(final Block block) {
- method.label(block.getBreakLabel());
- symbolInfo(block);
+ popBlockScope(block);
+ method.beforeJoinPoint(block);
+
+ closeBlockVariables(block);
+ lc.releaseSlots();
+ assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp() :
+ "reachable="+method.isReachable() +
+ " isFunctionBody=" + lc.isFunctionBody() +
+ " usedSlotCount=" + lc.getUsedSlotCount() +
+ " firstTemp=" + method.getFirstTemp();
- if (block.needsScope() && !block.isTerminal()) {
- popBlockScope(block);
- }
return block;
}
private void popBlockScope(final Block block) {
- final Label exitLabel = new Label("block_exit");
- final Label recoveryLabel = new Label("block_catch");
- final Label skipLabel = new Label("skip_catch");
+ final Label breakLabel = block.getBreakLabel();
- /* pop scope a la try-finally */
- method.loadCompilerConstant(SCOPE);
- method.invoke(ScriptObject.GET_PROTO);
- method.storeCompilerConstant(SCOPE);
- method._goto(skipLabel);
- method.label(exitLabel);
+ if(!block.needsScope() || lc.isFunctionBody()) {
+ emitBlockBreakLabel(breakLabel);
+ return;
+ }
+
+ final Label beginTryLabel = scopeEntryLabels.pop();
+ final Label recoveryLabel = new Label("block_popscope_catch");
+ emitBlockBreakLabel(breakLabel);
+ final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
+ if(bodyCanThrow) {
+ method._try(beginTryLabel, breakLabel, recoveryLabel);
+ }
+
+ Label afterCatchLabel = null;
+
+ if(method.isReachable()) {
+ popScope();
+ if(bodyCanThrow) {
+ afterCatchLabel = new Label("block_after_catch");
+ method._goto(afterCatchLabel);
+ }
+ }
+
+ if(bodyCanThrow) {
+ assert !method.isReachable();
+ method._catch(recoveryLabel);
+ popScopeException();
+ method.athrow();
+ }
+ if(afterCatchLabel != null) {
+ method.label(afterCatchLabel);
+ }
+ }
+
+ private void emitBlockBreakLabel(final Label breakLabel) {
+ // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
+ final LabelNode labelNode = lc.getCurrentBlockLabelNode();
+ if(labelNode != null) {
+ // Only have conversions if we're reachable
+ assert labelNode.getLocalVariableConversion() == null || method.isReachable();
+ method.beforeJoinPoint(labelNode);
+ method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
+ } else {
+ method.label(breakLabel);
+ }
+ }
+
+ private void popScope() {
+ popScopes(1);
+ }
+
+ /**
+ * Pop scope as part of an exception handler. Similar to {@code popScope()} but also takes care of adjusting the
+ * number of scopes that needs to be popped in case a rest-of continuation handler encounters an exception while
+ * performing a ToPrimitive conversion.
+ */
+ private void popScopeException() {
+ popScope();
+ final ContinuationInfo ci = getContinuationInfo();
+ if(ci != null) {
+ final Label catchLabel = ci.catchLabel;
+ if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
+ ++ci.exceptionScopePops;
+ }
+ }
+ }
- method._catch(recoveryLabel);
+ private void popScopesUntil(final LexicalContextNode until) {
+ popScopes(lc.getScopeNestingLevelTo(until));
+ }
+
+ private void popScopes(final int count) {
+ if(count == 0) {
+ return;
+ }
+ assert count > 0; // together with count == 0 check, asserts nonnegative count
+ if (!method.hasScope()) {
+ // We can sometimes invoke this method even if the method has no slot for the scope object. Typical example:
+ // for(;;) { with({}) { break; } }. WithNode normally creates a scope, but if it uses no identifiers and
+ // nothing else forces creation of a scope in the method, we just won't have the :scope local variable.
+ return;
+ }
method.loadCompilerConstant(SCOPE);
- method.invoke(ScriptObject.GET_PROTO);
+ for(int i = 0; i < count; ++i) {
+ method.invoke(ScriptObject.GET_PROTO);
+ }
method.storeCompilerConstant(SCOPE);
- method.athrow();
- method.label(skipLabel);
- method._try(block.getEntryLabel(), exitLabel, recoveryLabel, Throwable.class);
}
@Override
public boolean enterBreakNode(final BreakNode breakNode) {
- lineNumber(breakNode);
+ return enterJumpStatement(breakNode);
+ }
- final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabel());
- for (int i = 0; i < lc.getScopeNestingLevelTo(breakFrom); i++) {
- closeWith();
+ private boolean enterJumpStatement(final JumpStatement jump) {
+ if(!method.isReachable()) {
+ return false;
}
- method.splitAwareGoto(lc, breakFrom.getBreakLabel());
+ enterStatement(jump);
+
+ method.beforeJoinPoint(jump);
+ final BreakableNode target = jump.getTarget(lc);
+ popScopesUntil(target);
+ final Label targetLabel = jump.getTargetLabel(target);
+ targetLabel.markAsBreakTarget();
+ method._goto(targetLabel);
return false;
}
private int loadArgs(final List<Expression> args) {
- return loadArgs(args, null, false, args.size());
- }
-
- private int loadArgs(final List<Expression> args, final String signature, final boolean isVarArg, final int argCount) {
+ final int argCount = args.size();
// arg have already been converted to objects here.
- if (isVarArg || argCount > LinkerCallSite.ARGLIMIT) {
+ if (argCount > LinkerCallSite.ARGLIMIT) {
loadArgsArray(args);
return 1;
}
- // pad with undefined if size is too short. argCount is the real number of args
- int n = 0;
- final Type[] params = signature == null ? null : Type.getMethodArguments(signature);
for (final Expression arg : args) {
assert arg != null;
- if (n >= argCount) {
- load(arg);
- method.pop(); // we had to load the arg for its side effects
- } else if (params != null) {
- load(arg, params[n]);
- } else {
- load(arg);
- }
- n++;
+ loadExpressionUnbounded(arg);
}
-
- while (n < argCount) {
- method.loadUndefined(Type.OBJECT);
- n++;
- }
-
return argCount;
}
-
- @Override
- public boolean enterCallNode(final CallNode callNode) {
- return enterCallNode(callNode, callNode.getType());
- }
-
- private boolean enterCallNode(final CallNode callNode, final Type callNodeType) {
+ private boolean loadCallNode(final CallNode callNode, final TypeBounds resultBounds) {
lineNumber(callNode.getLineNumber());
final List<Expression> args = callNode.getArgs();
@@ -668,68 +1282,122 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
final Symbol symbol = identNode.getSymbol();
- int scopeCallFlags = flags;
- method.loadCompilerConstant(SCOPE);
- if (isFastScope(symbol)) {
- method.load(getScopeProtoDepth(currentBlock, symbol));
- scopeCallFlags |= CALLSITE_FAST_SCOPE;
- } else {
- method.load(-1); // Bypass fast-scope code in shared callsite
- }
- loadArgs(args);
- final Type[] paramTypes = method.getTypesFromStack(args.size());
- final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol, identNode.getType(), callNodeType, paramTypes, scopeCallFlags);
- return scopeCall.generateInvoke(method);
+ final boolean isFastScope = isFastScope(symbol);
+ final int scopeCallFlags = flags | (isFastScope ? CALLSITE_FAST_SCOPE : 0);
+ new OptimisticOperation(callNode, resultBounds) {
+ @Override
+ void loadStack() {
+ method.loadCompilerConstant(SCOPE);
+ if (isFastScope) {
+ method.load(getScopeProtoDepth(currentBlock, symbol));
+ } else {
+ method.load(-1); // Bypass fast-scope code in shared callsite
+ }
+ loadArgs(args);
+ }
+ @Override
+ void consumeStack() {
+ final Type[] paramTypes = method.getTypesFromStack(args.size());
+ // We have trouble finding e.g. in Type.typeFor(asm.Type) because it can't see the Context class
+ // loader, so we need to weaken reference signatures to Object.
+ for(int i = 0; i < paramTypes.length; ++i) {
+ paramTypes[i] = Type.generic(paramTypes[i]);
+ }
+ // As shared scope calls are only used in non-optimistic compilation, we switch from using
+ // TypeBounds to just a single definitive type, resultBounds.widest.
+ final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
+ identNode.getType(), resultBounds.widest, paramTypes, scopeCallFlags);
+ scopeCall.generateInvoke(method);
+ }
+ }.emit();
+ return method;
}
- private void scopeCall(final IdentNode node, final int flags) {
- load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
- // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
- method.loadUndefined(Type.OBJECT); //the 'this' object
- method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
+ private void scopeCall(final IdentNode ident, final int flags) {
+ new OptimisticOperation(callNode, resultBounds) {
+ int argsCount;
+ @Override
+ void loadStack() {
+ loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
+ // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
+ method.loadUndefined(Type.OBJECT); //the 'this'
+ argsCount = loadArgs(args);
+ }
+ @Override
+ void consumeStack() {
+ dynamicCall(2 + argsCount, flags);
+ }
+ }.emit();
}
- private void evalCall(final IdentNode node, final int flags) {
- load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
-
- final Label not_eval = new Label("not_eval");
+ private void evalCall(final IdentNode ident, final int flags) {
+ final Label invoke_direct_eval = new Label("invoke_direct_eval");
+ final Label is_not_eval = new Label("is_not_eval");
final Label eval_done = new Label("eval_done");
- // check if this is the real built-in eval
- method.dup();
- globalIsEval();
-
- method.ifeq(not_eval);
- // We don't need ScriptFunction object for 'eval'
- method.pop();
-
- method.loadCompilerConstant(SCOPE); // Load up self (scope).
-
- final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
- // load evaluated code
- load(evalArgs.getCode(), Type.OBJECT);
- // load second and subsequent args for side-effect
- final List<Expression> args = callNode.getArgs();
- final int numArgs = args.size();
- for (int i = 1; i < numArgs; i++) {
- load(args.get(i)).pop();
- }
- // special/extra 'eval' arguments
- load(evalArgs.getThis());
- method.load(evalArgs.getLocation());
- method.load(evalArgs.getStrictMode());
- method.convert(Type.OBJECT);
-
- // direct call to Global.directEval
- globalDirectEval();
- method.convert(callNodeType);
- method._goto(eval_done);
+ new OptimisticOperation(callNode, resultBounds) {
+ int argsCount;
+ @Override
+ void loadStack() {
+ /**
+ * We want to load 'eval' to check if it is indeed global builtin eval.
+ * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
+ * would be generated if ident is a "isFunction". But, that would result in a
+ * bound function from WithObject. We don't want that as bound function as that
+ * won't be detected as builtin eval. So, we make ident as "not a function" which
+ * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject
+ * would return unbounded eval function.
+ *
+ * Example:
+ *
+ * var global = this;
+ * function func() {
+ * with({ eval: global.eval) { eval("var x = 10;") }
+ * }
+ */
+ loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
+ globalIsEval();
+ method.ifeq(is_not_eval);
+
+ // Load up self (scope).
+ method.loadCompilerConstant(SCOPE);
+ final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
+ // load evaluated code
+ loadExpressionAsObject(evalArgs.get(0));
+ // load second and subsequent args for side-effect
+ final int numArgs = evalArgs.size();
+ for (int i = 1; i < numArgs; i++) {
+ loadAndDiscard(evalArgs.get(i));
+ }
+ method._goto(invoke_direct_eval);
+
+ method.label(is_not_eval);
+ // load this time but with dyn:getMethod|getProp|getElem
+ loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
+ // This is some scope 'eval' or global eval replaced by user
+ // but not the built-in ECMAScript 'eval' function call
+ method.loadNull();
+ argsCount = loadArgs(callNode.getArgs());
+ }
- method.label(not_eval);
- // This is some scope 'eval' or global eval replaced by user
- // but not the built-in ECMAScript 'eval' function call
- method.loadNull();
- method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
+ @Override
+ void consumeStack() {
+ // Ordinary call
+ dynamicCall(2 + argsCount, flags);
+ method._goto(eval_done);
+
+ method.label(invoke_direct_eval);
+ // Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
+ // them can ever be optimistic.
+ method.loadCompilerConstant(THIS);
+ method.load(callNode.getEvalArgs().getLocation());
+ method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
+ // direct call to Global.directEval
+ globalDirectEval();
+ convertOptimisticReturnValue();
+ coerceStackTop(resultBounds);
+ }
+ }.emit();
method.label(eval_done);
}
@@ -748,13 +1416,14 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
if (callNode.isEval()) {
evalCall(node, flags);
} else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
- || (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD)
- || CodeGenerator.this.lc.inDynamicScope()) {
+ || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
+ || CodeGenerator.this.lc.inDynamicScope()
+ || isOptimisticOrRestOf()) {
scopeCall(node, flags);
} else {
sharedScopeCall(node, flags);
}
- assert method.peekType().equals(callNodeType) : method.peekType() + "!=" + callNode.getType();
+ assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
} else {
enterDefault(node);
}
@@ -764,104 +1433,158 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
public boolean enterAccessNode(final AccessNode node) {
- load(node.getBase(), Type.OBJECT);
- method.dup();
- method.dynamicGet(node.getType(), node.getProperty().getName(), getCallSiteFlags(), true);
- method.swap();
- method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
+ //check if this is an apply to call node. only real applies, that haven't been
+ //shadowed from their way to the global scope counts
+
+ //call nodes have program points.
+
+ final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
+
+ new OptimisticOperation(callNode, resultBounds) {
+ int argCount;
+ @Override
+ void loadStack() {
+ loadExpressionAsObject(node.getBase());
+ method.dup();
+ // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
+ // a callable object. Nobody in their right mind would optimistically type this call site.
+ assert !node.isOptimistic();
+ method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
+ method.swap();
+ argCount = loadArgs(args);
+ }
+ @Override
+ void consumeStack() {
+ dynamicCall(2 + argCount, flags);
+ }
+ }.emit();
return false;
}
@Override
public boolean enterFunctionNode(final FunctionNode origCallee) {
- // NOTE: visiting the callee will leave a constructed ScriptFunction object on the stack if
- // callee.needsCallee() == true
- final FunctionNode callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
-
- final boolean isVarArg = callee.isVarArg();
- final int argCount = isVarArg ? -1 : callee.getParameters().size();
-
- final String signature = new FunctionSignature(true, callee.needsCallee(), callee.getReturnType(), isVarArg ? null : callee.getParameters()).toString();
+ new OptimisticOperation(callNode, resultBounds) {
+ FunctionNode callee;
+ int argsCount;
+ @Override
+ void loadStack() {
+ callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
+ if (callee.isStrict()) { // "this" is undefined
+ method.loadUndefined(Type.OBJECT);
+ } else { // get global from scope (which is the self)
+ globalInstance();
+ }
+ argsCount = loadArgs(args);
+ }
- if (callee.isStrict()) { // self is undefined
- method.loadUndefined(Type.OBJECT);
- } else { // get global from scope (which is the self)
- globalInstance();
- }
- loadArgs(args, signature, isVarArg, argCount);
- assert callee.getCompileUnit() != null : "no compile unit for " + callee.getName() + " " + Debug.id(callee) + " " + callNode;
- method.invokestatic(callee.getCompileUnit().getUnitClassName(), callee.getName(), signature);
- assert method.peekType().equals(callee.getReturnType()) : method.peekType() + " != " + callee.getReturnType();
- method.convert(callNodeType);
+ @Override
+ void consumeStack() {
+ final int flags = getCallSiteFlags();
+ //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
+ dynamicCall(2 + argsCount, flags);
+ }
+ }.emit();
return false;
}
@Override
public boolean enterIndexNode(final IndexNode node) {
- load(node.getBase(), Type.OBJECT);
- method.dup();
- final Type indexType = node.getIndex().getType();
- if (indexType.isObject() || indexType.isBoolean()) {
- load(node.getIndex(), Type.OBJECT); //TODO
- } else {
- load(node.getIndex());
- }
- method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
- method.swap();
- method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
-
+ new OptimisticOperation(callNode, resultBounds) {
+ int argsCount;
+ @Override
+ void loadStack() {
+ loadExpressionAsObject(node.getBase());
+ method.dup();
+ final Type indexType = node.getIndex().getType();
+ if (indexType.isObject() || indexType.isBoolean()) {
+ loadExpressionAsObject(node.getIndex()); //TODO boolean
+ } else {
+ loadExpressionUnbounded(node.getIndex());
+ }
+ // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
+ // back a callable object. Nobody in their right mind would optimistically type this call site.
+ assert !node.isOptimistic();
+ method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
+ method.swap();
+ argsCount = loadArgs(args);
+ }
+ @Override
+ void consumeStack() {
+ final int flags = getCallSiteFlags();
+ dynamicCall(2 + argsCount, flags);
+ }
+ }.emit();
return false;
}
@Override
protected boolean enterDefault(final Node node) {
- // Load up function.
- load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions
- method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
- method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
-
+ new OptimisticOperation(callNode, resultBounds) {
+ int argsCount;
+ @Override
+ void loadStack() {
+ // Load up function.
+ loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
+ method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
+ argsCount = loadArgs(args);
+ }
+ @Override
+ void consumeStack() {
+ final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
+ dynamicCall(2 + argsCount, flags);
+ }
+ }.emit();
return false;
}
});
- method.store(callNode.getSymbol());
-
return false;
}
+ /**
+ * Returns the flags with optimistic flag and program point removed.
+ * @param flags the flags that need optimism stripped from them.
+ * @return flags without optimism
+ */
+ static int nonOptimisticFlags(final int flags) {
+ return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
+ }
+
@Override
public boolean enterContinueNode(final ContinueNode continueNode) {
- lineNumber(continueNode);
-
- final LoopNode continueTo = lc.getContinueTo(continueNode.getLabel());
- for (int i = 0; i < lc.getScopeNestingLevelTo(continueTo); i++) {
- closeWith();
- }
- method.splitAwareGoto(lc, continueTo.getContinueLabel());
-
- return false;
+ return enterJumpStatement(continueNode);
}
@Override
public boolean enterEmptyNode(final EmptyNode emptyNode) {
- lineNumber(emptyNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(emptyNode);
return false;
}
@Override
public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
- lineNumber(expressionStatement);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(expressionStatement);
- expressionStatement.getExpression().accept(this);
+ loadAndDiscard(expressionStatement.getExpression());
+ assert method.getStackSize() == 0;
return false;
}
@Override
public boolean enterBlockStatement(final BlockStatement blockStatement) {
- lineNumber(blockStatement);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(blockStatement);
blockStatement.getBlock().accept(this);
@@ -870,83 +1593,79 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
public boolean enterForNode(final ForNode forNode) {
- lineNumber(forNode);
-
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(forNode);
if (forNode.isForIn()) {
enterForIn(forNode);
} else {
- enterFor(forNode);
+ final Expression init = forNode.getInit();
+ if (init != null) {
+ loadAndDiscard(init);
+ }
+ enterForOrWhile(forNode, forNode.getModify());
}
return false;
}
- private void enterFor(final ForNode forNode) {
- final Expression init = forNode.getInit();
- final Expression test = forNode.getTest();
- final Block body = forNode.getBody();
- final Expression modify = forNode.getModify();
-
- if (init != null) {
- init.accept(this);
- }
-
- final Label loopLabel = new Label("loop");
- final Label testLabel = new Label("test");
-
- method._goto(testLabel);
- method.label(loopLabel);
- body.accept(this);
- method.label(forNode.getContinueLabel());
-
- if (!body.isTerminal() && modify != null) {
- load(modify);
- }
-
- method.label(testLabel);
- if (test != null) {
- new BranchOptimizer(this, method).execute(test, loopLabel, true);
- } else {
- method._goto(loopLabel);
- }
-
- method.label(forNode.getBreakLabel());
- }
-
private void enterForIn(final ForNode forNode) {
- final Block body = forNode.getBody();
- final Expression modify = forNode.getModify();
-
- final Symbol iter = forNode.getIterator();
- final Label loopLabel = new Label("loop");
-
- final Expression init = forNode.getInit();
-
- load(modify, Type.OBJECT);
+ loadExpression(forNode.getModify(), TypeBounds.OBJECT);
method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
- method.store(iter);
- method._goto(forNode.getContinueLabel());
- method.label(loopLabel);
+ final Symbol iterSymbol = forNode.getIterator();
+ final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
+ method.store(iterSymbol, ITERATOR_TYPE);
+
+ method.beforeJoinPoint(forNode);
+
+ final Label continueLabel = forNode.getContinueLabel();
+ final Label breakLabel = forNode.getBreakLabel();
+
+ method.label(continueLabel);
+ method.load(ITERATOR_TYPE, iterSlot);
+ method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
+ final JoinPredecessorExpression test = forNode.getTest();
+ final Block body = forNode.getBody();
+ if(LocalVariableConversion.hasLiveConversion(test)) {
+ final Label afterConversion = new Label("for_in_after_test_conv");
+ method.ifne(afterConversion);
+ method.beforeJoinPoint(test);
+ method._goto(breakLabel);
+ method.label(afterConversion);
+ } else {
+ method.ifeq(breakLabel);
+ }
- new Store<Expression>(init) {
+ new Store<Expression>(forNode.getInit()) {
@Override
protected void storeNonDiscard() {
- return;
+ // This expression is neither part of a discard, nor needs to be left on the stack after it was
+ // stored, so we override storeNonDiscard to be a no-op.
}
+
@Override
protected void evaluate() {
- method.load(iter);
- method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
+ new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
+ @Override
+ void loadStack() {
+ method.load(ITERATOR_TYPE, iterSlot);
+ }
+
+ @Override
+ void consumeStack() {
+ method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
+ convertOptimisticReturnValue();
+ }
+ }.emit();
}
}.store();
-
body.accept(this);
- method.label(forNode.getContinueLabel());
- method.load(iter);
- method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
- method.ifne(loopLabel);
- method.label(forNode.getBreakLabel());
+ if(method.isReachable()) {
+ method._goto(continueLabel);
+ }
+ method.label(breakLabel);
}
/**
@@ -955,13 +1674,16 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* @param block block with local vars.
*/
private void initLocals(final Block block) {
- lc.nextFreeSlot(block);
+ lc.onEnterBlock(block);
final boolean isFunctionBody = lc.isFunctionBody();
-
final FunctionNode function = lc.getCurrentFunction();
if (isFunctionBody) {
- if(method.hasScope()) {
+ initializeMethodParameters(function);
+ if(!function.isVarArg()) {
+ expandParameterSlots(function);
+ }
+ if (method.hasScope()) {
if (function.needsParentScope()) {
method.loadCompilerConstant(CALLEE);
method.invoke(ScriptFunction.GET_SCOPE);
@@ -988,76 +1710,173 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// TODO for LET we can do better: if *block* does not contain any eval/with, we don't need its vars in scope.
- final List<String> nameList = new ArrayList<>();
- final List<Symbol> locals = new ArrayList<>();
-
- // Initalize symbols and values
- final List<Symbol> newSymbols = new ArrayList<>();
- final List<Symbol> values = new ArrayList<>();
-
final boolean hasArguments = function.needsArguments();
-
+ final List<MapTuple<Symbol>> tuples = new ArrayList<>();
+ final Iterator<IdentNode> paramIter = function.getParameters().iterator();
for (final Symbol symbol : block.getSymbols()) {
-
- if (symbol.isInternal() || symbol.isThis() || symbol.isTemp()) {
+ if (symbol.isInternal() || symbol.isThis()) {
continue;
}
if (symbol.isVar()) {
+ assert !varsInScope || symbol.isScope();
if (varsInScope || symbol.isScope()) {
- nameList.add(symbol.getName());
- newSymbols.add(symbol);
- values.add(null);
assert symbol.isScope() : "scope for " + symbol + " should have been set in Lower already " + function.getName();
assert !symbol.hasSlot() : "slot for " + symbol + " should have been removed in Lower already" + function.getName();
+
+ //this tuple will not be put fielded, as it has no value, just a symbol
+ tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, null));
} else {
- assert symbol.hasSlot() : symbol + " should have a slot only, no scope";
- locals.add(symbol);
+ assert symbol.hasSlot() || symbol.slotCount() == 0 : symbol + " should have a slot only, no scope";
}
} else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
- nameList.add(symbol.getName());
- newSymbols.add(symbol);
- values.add(hasArguments ? null : symbol);
- assert symbol.isScope() : "scope for " + symbol + " should have been set in Lower already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
+ assert symbol.isScope() : "scope for " + symbol + " should have been set in AssignSymbols already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
assert !(hasArguments && symbol.hasSlot()) : "slot for " + symbol + " should have been removed in Lower already " + function.getName();
+
+ final Type paramType;
+ final Symbol paramSymbol;
+
+ if (hasArguments) {
+ assert !symbol.hasSlot() : "slot for " + symbol + " should have been removed in Lower already ";
+ paramSymbol = null;
+ paramType = null;
+ } else {
+ paramSymbol = symbol;
+ // NOTE: We're relying on the fact here that Block.symbols is a LinkedHashMap, hence it will
+ // return symbols in the order they were defined, and parameters are defined in the same order
+ // they appear in the function. That's why we can have a single pass over the parameter list
+ // with an iterator, always just scanning forward for the next parameter that matches the symbol
+ // name.
+ for(;;) {
+ final IdentNode nextParam = paramIter.next();
+ if(nextParam.getName().equals(symbol.getName())) {
+ paramType = nextParam.getType();
+ break;
+ }
+ }
+ }
+
+ tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
+ //this symbol will be put fielded, we can't initialize it as undefined with a known type
+ @Override
+ public Class<?> getValueType() {
+ if (OBJECT_FIELDS_ONLY || value == null || paramType == null) {
+ return Object.class;
+ }
+ return paramType.isBoolean() ? Object.class : paramType.getTypeClass();
+ }
+ });
}
}
- // we may have locals that need to be initialized
- initSymbols(locals);
-
/*
* Create a new object based on the symbols and values, generate
* bootstrap code for object
*/
- new FieldObjectCreator<Symbol>(this, nameList, newSymbols, values, true, hasArguments) {
+ new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
@Override
- protected void loadValue(final Symbol value) {
- method.load(value);
+ protected void loadValue(final Symbol value, final Type type) {
+ method.load(value, type);
}
}.makeObject(method);
-
- // runScript(): merge scope into global
+ // program function: merge scope into global
if (isFunctionBody && function.isProgram()) {
method.invoke(ScriptRuntime.MERGE_SCOPE);
}
method.storeCompilerConstant(SCOPE);
- } else {
+ if(!isFunctionBody) {
+ // Function body doesn't need a try/catch to restore scope, as it'd be a dead store anyway. Allowing it
+ // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
+ // the top of the exception handler table, so it'll be triggered instead of the UOE handlers.
+ final Label scopeEntryLabel = new Label("scope_entry");
+ scopeEntryLabels.push(scopeEntryLabel);
+ method.label(scopeEntryLabel);
+ }
+ } else if (isFunctionBody && function.isVarArg()) {
// Since we don't have a scope, parameters didn't get assigned array indices by the FieldObjectCreator, so
// we need to assign them separately here.
int nextParam = 0;
- if (isFunctionBody && function.isVarArg()) {
- for (final IdentNode param : function.getParameters()) {
- param.getSymbol().setFieldIndex(nextParam++);
- }
+ for (final IdentNode param : function.getParameters()) {
+ param.getSymbol().setFieldIndex(nextParam++);
}
-
- initSymbols(block.getSymbols());
}
// Debugging: print symbols? @see --print-symbols flag
- printSymbols(block, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
+ printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
+ }
+
+ /**
+ * Incoming method parameters are always declared on method entry; declare them in the local variable table.
+ * @param function function for which code is being generated.
+ */
+ private void initializeMethodParameters(final FunctionNode function) {
+ final Label functionStart = new Label("fn_start");
+ method.label(functionStart);
+ int nextSlot = 0;
+ if(function.needsCallee()) {
+ initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
+ }
+ initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
+ if(function.isVarArg()) {
+ initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
+ } else {
+ for(final IdentNode param: function.getParameters()) {
+ final Symbol symbol = param.getSymbol();
+ if(symbol.isBytecodeLocal()) {
+ method.initializeMethodParameter(symbol, param.getType(), functionStart);
+ }
+ }
+ }
+ }
+
+ private void initializeInternalFunctionParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
+ final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
+ // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
+ assert symbol.getFirstSlot() == slot;
+ }
+
+ private Symbol initializeInternalFunctionOrSplitParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
+ final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
+ final Type type = Type.typeFor(cc.type());
+ method.initializeMethodParameter(symbol, type, functionStart);
+ method.onLocalStore(type, slot);
+ return symbol;
+ }
+
+ /**
+ * Parameters come into the method packed into local variable slots next to each other. Nashorn on the other hand
+ * can use 1-6 slots for a local variable depending on all the types it needs to store. When this method is invoked,
+ * the symbols are already allocated such wider slots, but the values are still in tightly packed incoming slots,
+ * and we need to spread them into their new locations.
+ * @param function the function for which parameter-spreading code needs to be emitted
+ */
+ private void expandParameterSlots(final FunctionNode function) {
+ final List<IdentNode> parameters = function.getParameters();
+ // Calculate the total number of incoming parameter slots
+ int currentIncomingSlot = function.needsCallee() ? 2 : 1;
+ for(final IdentNode parameter: parameters) {
+ currentIncomingSlot += parameter.getType().getSlots();
+ }
+ // Starting from last parameter going backwards, move the parameter values into their new slots.
+ for(int i = parameters.size(); i-- > 0;) {
+ final IdentNode parameter = parameters.get(i);
+ final Type parameterType = parameter.getType();
+ final int typeWidth = parameterType.getSlots();
+ currentIncomingSlot -= typeWidth;
+ final Symbol symbol = parameter.getSymbol();
+ final int slotCount = symbol.slotCount();
+ assert slotCount > 0;
+ // Scoped parameters must not hold more than one value
+ assert symbol.isBytecodeLocal() || slotCount == typeWidth;
+
+ // Mark it as having its value stored into it by the method invocation.
+ method.onLocalStore(parameterType, currentIncomingSlot);
+ if(currentIncomingSlot != symbol.getSlot(parameterType)) {
+ method.load(parameterType, currentIncomingSlot);
+ method.store(symbol, parameterType);
+ }
+ }
}
private void initArguments(final FunctionNode function) {
@@ -1075,15 +1894,45 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.storeCompilerConstant(ARGUMENTS);
}
+ private boolean skipFunction(final FunctionNode functionNode) {
+ final ScriptEnvironment env = compiler.getScriptEnvironment();
+ final boolean lazy = env._lazy_compilation;
+ final boolean onDemand = compiler.isOnDemandCompilation();
+
+ // If this is on-demand or lazy compilation, don't compile a nested (not topmost) function.
+ if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
+ return true;
+ }
+
+ // If lazy compiling with optimistic types, don't compile the program eagerly either. It will soon be
+ // invalidated anyway. In presence of a class cache, this further means that an obsoleted program version
+ // lingers around. Also, currently loading previously persisted optimistic types information only works if
+ // we're on-demand compiling a function, so with this strategy the :program method can also have the warmup
+ // benefit of using previously persisted types.
+ //
+ // NOTE that this means the first compiled class will effectively just have a :createProgramFunction method, and
+ // the RecompilableScriptFunctionData (RSFD) object in its constants array. It won't even have the :program
+ // method. This is by design. It does mean that we're wasting one compiler execution (and we could minimize this
+ // by just running it up to scope depth calculation, which creates the RSFDs and then this limited codegen).
+ // We could emit an initial separate compile unit with the initial version of :program in it to better utilize
+ // the compilation pipeline, but that would need more invasive changes, as currently the assumption that
+ // :program is emitted into the first compilation unit of the function lives in many places.
+ return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
+ }
+
@Override
public boolean enterFunctionNode(final FunctionNode functionNode) {
- if (functionNode.isLazy()) {
- // Must do it now; can't postpone it until leaveFunctionNode()
- newFunctionObject(functionNode, functionNode);
+ final int fnId = functionNode.getId();
+
+ if (skipFunction(functionNode)) {
+ // In case we are not generating code for the function, we must create or retrieve the function object and
+ // load it on the stack here.
+ newFunctionObject(functionNode, false);
return false;
}
final String fnName = functionNode.getName();
+
// NOTE: we only emit the method for a function with the given name once. We can have multiple functions with
// the same name as a result of inlining finally blocks. However, in the future -- with type specialization,
// notably -- we might need to check for both name *and* signature. Of course, even that might not be
@@ -1092,35 +1941,67 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// to decide to either generate a unique method for each inlined copy of the function, maybe figure out its
// exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
// worth it, and generate one method with most generic type closure.
- if(!emittedMethods.contains(fnName)) {
- LOG.info("=== BEGIN ", fnName);
+ if (!emittedMethods.contains(fnName)) {
+ log.info("=== BEGIN ", fnName);
assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
unit = lc.pushCompileUnit(functionNode.getCompileUnit());
assert lc.hasCompileUnits();
- method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
+ final ClassEmitter classEmitter = unit.getClassEmitter();
+ pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
+ method.setPreventUndefinedLoad();
+ if(useOptimisticTypes()) {
+ lc.pushUnwarrantedOptimismHandlers();
+ }
+
// new method - reset last line number
lastLineNumber = -1;
- // Mark end for variable tables.
+
method.begin();
+
+ if (isRestOf()) {
+ final ContinuationInfo ci = new ContinuationInfo();
+ fnIdToContinuationInfo.put(fnId, ci);
+ method.gotoLoopStart(ci.getHandlerLabel());
+ }
}
return true;
}
+ private void pushMethodEmitter(final MethodEmitter newMethod) {
+ method = lc.pushMethodEmitter(newMethod);
+ catchLabels.push(METHOD_BOUNDARY);
+ }
+
+ private void popMethodEmitter() {
+ method = lc.popMethodEmitter(method);
+ assert catchLabels.peek() == METHOD_BOUNDARY;
+ catchLabels.pop();
+ }
+
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
try {
- if(emittedMethods.add(functionNode.getName())) {
+ final boolean markOptimistic;
+ if (emittedMethods.add(functionNode.getName())) {
+ markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
+ generateContinuationHandler();
method.end(); // wrap up this method
unit = lc.popCompileUnit(functionNode.getCompileUnit());
- method = lc.popMethodEmitter(method);
- LOG.info("=== END ", functionNode.getName());
+ popMethodEmitter();
+ log.info("=== END ", functionNode.getName());
+ } else {
+ markOptimistic = false;
+ }
+
+ FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
+ if (markOptimistic) {
+ newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
}
- final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED);
- newFunctionObject(newFunctionNode, functionNode);
+ newFunctionObject(newFunctionNode, true);
return newFunctionNode;
} catch (final Throwable t) {
Context.printStackTrace(t);
@@ -1131,62 +2012,75 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
- public boolean enterIdentNode(final IdentNode identNode) {
- return false;
- }
-
- @Override
public boolean enterIfNode(final IfNode ifNode) {
- lineNumber(ifNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(ifNode);
final Expression test = ifNode.getTest();
final Block pass = ifNode.getPass();
final Block fail = ifNode.getFail();
- final Label failLabel = new Label("if_fail");
- final Label afterLabel = fail == null ? failLabel : new Label("if_done");
+ if (Expression.isAlwaysTrue(test)) {
+ loadAndDiscard(test);
+ pass.accept(this);
+ return false;
+ } else if (Expression.isAlwaysFalse(test)) {
+ loadAndDiscard(test);
+ if (fail != null) {
+ fail.accept(this);
+ }
+ return false;
+ }
- new BranchOptimizer(this, method).execute(test, failLabel, false);
+ final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
- boolean passTerminal = false;
- boolean failTerminal = false;
+ final Label failLabel = new Label("if_fail");
+ final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");
+
+ emitBranch(test, failLabel, false);
pass.accept(this);
- if (!pass.hasTerminalFlags()) {
+ if(method.isReachable() && afterLabel != null) {
method._goto(afterLabel); //don't fallthru to fail block
- } else {
- passTerminal = pass.isTerminal();
}
+ method.label(failLabel);
if (fail != null) {
- method.label(failLabel);
fail.accept(this);
- failTerminal = fail.isTerminal();
+ } else if(hasFailConversion) {
+ method.beforeJoinPoint(ifNode);
}
- //if if terminates, put the after label there
- if (!passTerminal || !failTerminal) {
+ if(afterLabel != null && afterLabel.isReachable()) {
method.label(afterLabel);
}
return false;
}
- @Override
- public boolean enterIndexNode(final IndexNode indexNode) {
- load(indexNode);
- return false;
+ private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
+ new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
+ }
+
+ private void enterStatement(final Statement statement) {
+ lineNumber(statement);
}
private void lineNumber(final Statement statement) {
lineNumber(statement.getLineNumber());
}
- private void lineNumber(int lineNumber) {
- if (lineNumber != lastLineNumber) {
+ private void lineNumber(final int lineNumber) {
+ if (lineNumber != lastLineNumber && lineNumber != Node.NO_LINE_NUMBER) {
method.lineNumber(lineNumber);
+ lastLineNumber = lineNumber;
}
- lastLineNumber = lineNumber;
+ }
+
+ int getLastLineNumber() {
+ return lastLineNumber;
}
/**
@@ -1219,26 +2113,35 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
final String className = unit.getUnitClassName();
+ assert unit != null;
final String name = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
- final MethodEmitter me = unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature);
- method = lc.pushMethodEmitter(me);
+ pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
method.setFunctionNode(currentFunction);
method.begin();
- fixScopeSlot(currentFunction);
+ defineCommonSplitMethodParameters();
+ defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
+
+ // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
+ // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
+ final int arraySlot = fixScopeSlot(currentFunction, 3);
- method.load(arrayType, SPLIT_ARRAY_ARG.slot());
+ lc.enterSplitNode();
for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
+ method.load(arrayType, arraySlot);
storeElement(nodes, elementType, postsets[i]);
}
+ method.load(arrayType, arraySlot);
method._return();
+ lc.exitSplitNode();
method.end();
- method = lc.popMethodEmitter(me);
+ lc.releaseSlots();
+ popMethodEmitter();
assert method == savedMethod;
method.loadCompilerConstant(CALLEE);
@@ -1255,15 +2158,19 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return method;
}
- for (final int postset : postsets) {
- storeElement(nodes, elementType, postset);
+ if(postsets.length > 0) {
+ final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
+ method.storeTemp(arrayType, arraySlot);
+ for (final int postset : postsets) {
+ method.load(arrayType, arraySlot);
+ storeElement(nodes, elementType, postset);
+ }
+ method.load(arrayType, arraySlot);
}
-
return method;
}
private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
- method.dup();
method.load(index);
final Expression element = nodes[index];
@@ -1271,7 +2178,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
if (element == null) {
method.loadEmpty(elementType);
} else {
- load(element, elementType);
+ loadExpressionAsType(element, elementType);
}
method.arraystore();
@@ -1284,7 +2191,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
for (int i = 0; i < args.size(); i++) {
method.dup();
method.load(i);
- load(args.get(i), Type.OBJECT); //has to be upcast to object or we fail
+ loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
method.arraystore();
}
@@ -1314,44 +2221,48 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* @param object object to load
*/
void loadConstant(final Object object) {
- final String unitClassName = unit.getUnitClassName();
- final ClassEmitter classEmitter = unit.getClassEmitter();
+ loadConstant(object, unit, method);
+ }
+
+ private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
+ final String unitClassName = compileUnit.getUnitClassName();
+ final ClassEmitter classEmitter = compileUnit.getClassEmitter();
final int index = compiler.getConstantData().add(object);
final Class<?> cls = object.getClass();
if (cls == PropertyMap.class) {
- method.load(index);
- method.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
+ methodEmitter.load(index);
+ methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
classEmitter.needGetConstantMethod(PropertyMap.class);
} else if (cls.isArray()) {
- method.load(index);
+ methodEmitter.load(index);
final String methodName = ClassEmitter.getArrayMethodName(cls);
- method.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
+ methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
classEmitter.needGetConstantMethod(cls);
} else {
- method.loadConstants().load(index).arrayload();
+ methodEmitter.loadConstants().load(index).arrayload();
if (object instanceof ArrayData) {
// avoid cast to non-public ArrayData subclass
- method.checkcast(ArrayData.class);
- method.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
+ methodEmitter.checkcast(ArrayData.class);
+ methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
} else if (cls != Object.class) {
- method.checkcast(cls);
+ methodEmitter.checkcast(cls);
}
}
}
// literal values
- private MethodEmitter loadLiteral(final LiteralNode<?> node, final Type type) {
+ private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
final Object value = node.getValue();
if (value == null) {
method.loadNull();
} else if (value instanceof Undefined) {
- method.loadUndefined(Type.OBJECT);
+ method.loadUndefined(resultBounds.within(Type.OBJECT));
} else if (value instanceof String) {
final String string = (String)value;
- if (string.length() > (MethodEmitter.LARGE_STRING_THRESHOLD / 3)) { // 3 == max bytes per encoded char
+ if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
loadConstant(string);
} else {
method.load(string);
@@ -1361,31 +2272,40 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
} else if (value instanceof Boolean) {
method.load((Boolean)value);
} else if (value instanceof Integer) {
- if(type.isEquivalentTo(Type.NUMBER)) {
+ if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+ method.load((Integer)value);
+ method.convert(Type.OBJECT);
+ } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
method.load(((Integer)value).doubleValue());
- } else if(type.isEquivalentTo(Type.LONG)) {
+ } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) {
method.load(((Integer)value).longValue());
} else {
method.load((Integer)value);
}
} else if (value instanceof Long) {
- if(type.isEquivalentTo(Type.NUMBER)) {
+ if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+ method.load((Long)value);
+ method.convert(Type.OBJECT);
+ } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
method.load(((Long)value).doubleValue());
} else {
method.load((Long)value);
}
} else if (value instanceof Double) {
- method.load((Double)value);
+ if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+ method.load((Double)value);
+ method.convert(Type.OBJECT);
+ } else {
+ method.load((Double)value);
+ }
} else if (node instanceof ArrayLiteralNode) {
final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
final ArrayType atype = arrayLiteral.getArrayType();
loadArray(arrayLiteral, atype);
globalAllocateArray(atype);
} else {
- assert false : "Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value;
+ throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
}
-
- return method;
}
private MethodEmitter loadRegexToken(final RegexToken value) {
@@ -1422,35 +2342,65 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return method;
}
- @Override
- public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
- return enterLiteralNode(literalNode, literalNode.getType());
- }
+ /**
+ * Check if a property value contains a particular program point
+ * @param value value
+ * @param pp program point
+ * @return true if it's there.
+ */
+ private static boolean propertyValueContains(final Expression value, final int pp) {
+ return new Supplier<Boolean>() {
+ boolean contains;
- private boolean enterLiteralNode(final LiteralNode<?> literalNode, final Type type) {
- assert literalNode.getSymbol() != null : literalNode + " has no symbol";
- loadLiteral(literalNode, type).convert(type).store(literalNode.getSymbol());
- return false;
+ @Override
+ public Boolean get() {
+ value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ return false;
+ }
+
+ @Override
+ public boolean enterObjectNode(final ObjectNode objectNode) {
+ return false;
+ }
+
+ @Override
+ public boolean enterDefault(final Node node) {
+ if (contains) {
+ return false;
+ }
+ if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) {
+ contains = true;
+ return false;
+ }
+ return true;
+ }
+ });
+
+ return contains;
+ }
+ }.get();
}
- @Override
- public boolean enterObjectNode(final ObjectNode objectNode) {
+ private void loadObjectNode(final ObjectNode objectNode) {
final List<PropertyNode> elements = objectNode.getElements();
- final List<String> keys = new ArrayList<>();
- final List<Symbol> symbols = new ArrayList<>();
- final List<Expression> values = new ArrayList<>();
+ final List<MapTuple<Expression>> tuples = new ArrayList<>();
+ final List<PropertyNode> gettersSetters = new ArrayList<>();
+ final int ccp = getCurrentContinuationEntryPoint();
- boolean hasGettersSetters = false;
Expression protoNode = null;
+ boolean restOfProperty = false;
- for (PropertyNode propertyNode: elements) {
- final Expression value = propertyNode.getValue();
- final String key = propertyNode.getKeyName();
- final Symbol symbol = value == null ? null : propertyNode.getKey().getSymbol();
+ for (final PropertyNode propertyNode : elements) {
+ final Expression value = propertyNode.getValue();
+ final String key = propertyNode.getKeyName();
+ // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
+ final Symbol symbol = value == null ? null : new Symbol(key, 0);
if (value == null) {
- hasGettersSetters = true;
+ gettersSetters.add(propertyNode);
} else if (propertyNode.getKey() instanceof IdentNode &&
key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
// ES6 draft compliant __proto__ inside object literal
@@ -1459,89 +2409,84 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
continue;
}
- keys.add(key);
- symbols.add(symbol);
- values.add(value);
- }
+ restOfProperty |=
+ value != null &&
+ isValid(ccp) &&
+ propertyValueContains(value, ccp);
- if (elements.size() > OBJECT_SPILL_THRESHOLD) {
- new SpillObjectCreator(this, keys, symbols, values).makeObject(method);
- } else {
- new FieldObjectCreator<Expression>(this, keys, symbols, values) {
+ //for literals, a value of null means object type, i.e. the value null or getter setter function
+ //(I think)
+ final Class<?> valueType = (OBJECT_FIELDS_ONLY || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
+ tuples.add(new MapTuple<Expression>(key, symbol, Type.typeFor(valueType), value) {
@Override
- protected void loadValue(final Expression node) {
- load(node);
+ public Class<?> getValueType() {
+ return type.getTypeClass();
}
+ });
+ }
- /**
- * Ensure that the properties start out as object types so that
- * we can do putfield initializations instead of dynamicSetIndex
- * which would be the case to determine initial property type
- * otherwise.
- *
- * Use case, it's very expensive to do a million var x = {a:obj, b:obj}
- * just to have to invalidate them immediately on initialization
- *
- * see NASHORN-594
- */
+ final ObjectCreator<?> oc;
+ if (elements.size() > OBJECT_SPILL_THRESHOLD) {
+ oc = new SpillObjectCreator(this, tuples);
+ } else {
+ oc = new FieldObjectCreator<Expression>(this, tuples) {
@Override
- protected MapCreator newMapCreator(final Class<?> fieldObjectClass) {
- return new MapCreator(fieldObjectClass, keys, symbols) {
- @Override
- protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) {
- return super.getPropertyFlags(symbol, hasArguments) | Property.IS_ALWAYS_OBJECT;
- }
- };
- }
-
- }.makeObject(method);
+ protected void loadValue(final Expression node, final Type type) {
+ loadExpressionAsType(node, type);
+ }};
+ }
+ oc.makeObject(method);
+
+ //if this is a rest of method and our continuation point was found as one of the values
+ //in the properties above, we need to reset the map to oc.getMap() in the continuation
+ //handler
+ if (restOfProperty) {
+ final ContinuationInfo ci = getContinuationInfo();
+ // Can be set at most once for a single rest-of method
+ assert ci.getObjectLiteralMap() == null;
+ ci.setObjectLiteralMap(oc.getMap());
+ ci.setObjectLiteralStackDepth(method.getStackSize());
}
method.dup();
if (protoNode != null) {
- load(protoNode);
+ loadExpressionAsObject(protoNode);
// take care of { __proto__: 34 } or some such!
method.convert(Type.OBJECT);
method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
} else {
- globalObjectPrototype();
- method.invoke(ScriptObject.SET_PROTO);
+ method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
}
- if (hasGettersSetters) {
- for (final PropertyNode propertyNode : elements) {
- final FunctionNode getter = propertyNode.getGetter();
- final FunctionNode setter = propertyNode.getSetter();
-
- if (getter == null && setter == null) {
- continue;
- }
-
- method.dup().loadKey(propertyNode.getKey());
+ for (final PropertyNode propertyNode : gettersSetters) {
+ final FunctionNode getter = propertyNode.getGetter();
+ final FunctionNode setter = propertyNode.getSetter();
- if (getter == null) {
- method.loadNull();
- } else {
- getter.accept(this);
- }
+ assert getter != null || setter != null;
- if (setter == null) {
- method.loadNull();
- } else {
- setter.accept(this);
- }
+ method.dup().loadKey(propertyNode.getKey());
+ if (getter == null) {
+ method.loadNull();
+ } else {
+ getter.accept(this);
+ }
- method.invoke(ScriptObject.SET_USER_ACCESSORS);
+ if (setter == null) {
+ method.loadNull();
+ } else {
+ setter.accept(this);
}
- }
- method.store(objectNode.getSymbol());
- return false;
+ method.invoke(ScriptObject.SET_USER_ACCESSORS);
+ }
}
@Override
public boolean enterReturnNode(final ReturnNode returnNode) {
- lineNumber(returnNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(returnNode);
method.registerReturn();
@@ -1549,7 +2494,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final Expression expression = returnNode.getExpression();
if (expression != null) {
- load(expression);
+ loadExpressionUnbounded(expression);
} else {
method.loadUndefined(returnType);
}
@@ -1559,11 +2504,83 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return false;
}
+ private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
+ final Request request = runtimeNode.getRequest();
+
+ if (!Request.isUndefinedCheck(request)) {
+ return false;
+ }
+
+ final Expression lhs = args.get(0);
+ final Expression rhs = args.get(1);
+
+ final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
+ final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
+ // One must be a "undefined" identifier, otherwise we can't get here
+ assert lhsSymbol != null || rhsSymbol != null;
+
+ final Symbol undefinedSymbol;
+ if (isUndefinedSymbol(lhsSymbol)) {
+ undefinedSymbol = lhsSymbol;
+ } else {
+ assert isUndefinedSymbol(rhsSymbol);
+ undefinedSymbol = rhsSymbol;
+ }
+
+ assert undefinedSymbol != null; //remove warning
+ if (!undefinedSymbol.isScope()) {
+ return false; //disallow undefined as local var or parameter
+ }
+
+ if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
+ //we load the undefined first. never mind, because this will deoptimize anyway
+ return false;
+ }
+
+ if(isDeoptimizedExpression(lhs)) {
+ // This is actually related to "lhs.getType().isPrimitive()" above: any expression being deoptimized in
+ // the current chain of rest-of compilations used to have a type narrower than Object (so it was primitive).
+ // We must not perform undefined check specialization for them, as then we'd violate the basic rule of
+ // "Thou shalt not alter the stack shape between a deoptimized method and any of its (transitive) rest-ofs."
+ return false;
+ }
+
+ //make sure that undefined has not been overridden or scoped as a local var
+ //between us and global
+ if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
+ return false;
+ }
+
+ final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
+ final Expression expr = undefinedSymbol == lhsSymbol ? rhs : lhs;
+ if (expr.getType().isPrimitive()) {
+ loadAndDiscard(expr); //throw away lhs, but it still needs to be evaluated for side effects, even if not in scope, as it can be optimistic
+ method.load(!isUndefinedCheck);
+ } else {
+ final Label checkTrue = new Label("ud_check_true");
+ final Label end = new Label("end");
+ loadExpressionAsObject(expr);
+ method.loadUndefined(Type.OBJECT);
+ method.if_acmpeq(checkTrue);
+ method.load(!isUndefinedCheck);
+ method._goto(end);
+ method.label(checkTrue);
+ method.load(isUndefinedCheck);
+ method.label(end);
+ }
+
+ return true;
+ }
+
+ private static boolean isUndefinedSymbol(final Symbol symbol) {
+ return symbol != null && "undefined".equals(symbol.getName());
+ }
+
private static boolean isNullLiteral(final Node node) {
return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
}
- private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args, final String signature) {
+ private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
final Request request = runtimeNode.getRequest();
if (!Request.isEQ(request) && !Request.isNE(request)) {
@@ -1581,344 +2598,239 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
rhs = tmp;
}
+ if (!isNullLiteral(rhs)) {
+ return false;
+ }
+
+ if (!lhs.getType().isObject()) {
+ return false;
+ }
+
+ if(isDeoptimizedExpression(lhs)) {
+ // This is actually related to "!lhs.getType().isObject()" above: any expression being deoptimized in
+ // the current chain of rest-of compilations used to have a type narrower than Object. We must not
+ // perform null check specialization for them, as then we'd no longer be loading aconst_null on stack
+ // and thus violate the basic rule of "Thou shalt not alter the stack shape between a deoptimized
+ // method and any of its (transitive) rest-ofs."
+ // NOTE also that if we had a representation for well-known constants (e.g. null, 0, 1, -1, etc.) in
+ // Label$Stack.localLoads then this wouldn't be an issue, as we would never (somewhat ridiculously)
+ // allocate a temporary local to hold the result of aconst_null before attempting an optimistic
+ // operation.
+ return false;
+ }
+
// this is a null literal check, so if there is implicit coercion
// involved like {D}x=null, we will fail - this is very rare
- if (isNullLiteral(rhs) && lhs.getType().isObject()) {
- final Label trueLabel = new Label("trueLabel");
- final Label falseLabel = new Label("falseLabel");
- final Label endLabel = new Label("end");
+ final Label trueLabel = new Label("trueLabel");
+ final Label falseLabel = new Label("falseLabel");
+ final Label endLabel = new Label("end");
+
+ loadExpressionUnbounded(lhs); //lhs
+ final Label popLabel;
+ if (!Request.isStrict(request)) {
+ method.dup(); //lhs lhs
+ popLabel = new Label("pop");
+ } else {
+ popLabel = null;
+ }
- load(lhs);
- method.dup();
- if (Request.isEQ(request)) {
- method.ifnull(trueLabel);
- } else if (Request.isNE(request)) {
- method.ifnonnull(trueLabel);
- } else {
- assert false : "Invalid request " + request;
+ if (Request.isEQ(request)) {
+ method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
+ if (!Request.isStrict(request)) {
+ method.loadUndefined(Type.OBJECT);
+ method.if_acmpeq(trueLabel);
}
-
method.label(falseLabel);
- load(rhs);
- method.invokestatic(CompilerConstants.className(ScriptRuntime.class), request.toString(), signature);
+ method.load(false);
method._goto(endLabel);
-
+ if (!Request.isStrict(request)) {
+ method.label(popLabel);
+ method.pop();
+ }
method.label(trueLabel);
- // if NE (not strict) this can be "undefined != null" which is supposed to be false
- if (request == Request.NE) {
+ method.load(true);
+ method.label(endLabel);
+ } else if (Request.isNE(request)) {
+ method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
+ if (!Request.isStrict(request)) {
method.loadUndefined(Type.OBJECT);
- final Label isUndefined = new Label("isUndefined");
- final Label afterUndefinedCheck = new Label("afterUndefinedCheck");
- method.if_acmpeq(isUndefined);
- // not undefined
- method.load(true);
- method._goto(afterUndefinedCheck);
- method.label(isUndefined);
- method.load(false);
- method.label(afterUndefinedCheck);
- } else {
+ method.if_acmpeq(falseLabel);
+ }
+ method.label(trueLabel);
+ method.load(true);
+ method._goto(endLabel);
+ if (!Request.isStrict(request)) {
+ method.label(popLabel);
method.pop();
- method.load(true);
}
+ method.label(falseLabel);
+ method.load(false);
method.label(endLabel);
- method.convert(runtimeNode.getType());
- method.store(runtimeNode.getSymbol());
-
- return true;
}
- return false;
+ assert runtimeNode.getType().isBoolean();
+ method.convert(runtimeNode.getType());
+
+ return true;
}
- private boolean specializationCheck(final RuntimeNode.Request request, final Expression node, final List<Expression> args) {
- if (!request.canSpecialize()) {
+ /**
+ * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods?
+ * @param rootExpr the expression being tested
+ * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain.
+ */
+ private boolean isDeoptimizedExpression(final Expression rootExpr) {
+ if(!isRestOf()) {
return false;
}
-
- assert args.size() == 2;
- final Type returnType = node.getType();
-
- load(args.get(0));
- load(args.get(1));
-
- Request finalRequest = request;
-
- //if the request is a comparison, i.e. one that can be reversed
- //it keeps its semantic, but make sure that the object comes in
- //last
- final Request reverse = Request.reverse(request);
- if (method.peekType().isObject() && reverse != null) { //rhs is object
- if (!method.peekType(1).isObject()) { //lhs is not object
- method.swap(); //prefer object as lhs
- finalRequest = reverse;
+ return new Supplier<Boolean>() {
+ boolean contains;
+ @Override
+ public Boolean get() {
+ rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ return false;
+ }
+ @Override
+ public boolean enterDefault(final Node node) {
+ if(!contains && node instanceof Optimistic) {
+ final int pp = ((Optimistic)node).getProgramPoint();
+ contains = isValid(pp) && isContinuationEntryPoint(pp);
+ }
+ return !contains;
+ }
+ });
+ return contains;
}
- }
-
- method.dynamicRuntimeCall(
- new SpecializedRuntimeNode(
- finalRequest,
- new Type[] {
- method.peekType(1),
- method.peekType()
- },
- returnType).getInitialName(),
- returnType,
- finalRequest);
-
- method.convert(node.getType());
- method.store(node.getSymbol());
-
- return true;
- }
-
- private static boolean isReducible(final Request request) {
- return Request.isComparison(request) || request == Request.ADD;
+ }.get();
}
- @Override
- public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
- /*
- * First check if this should be something other than a runtime node
- * AccessSpecializer might have changed the type
- *
- * TODO - remove this - Access Specializer will always know after Attr/Lower
- */
- final List<Expression> args = runtimeNode.getArgs();
- if (runtimeNode.isPrimitive() && !runtimeNode.isFinal() && isReducible(runtimeNode.getRequest())) {
- final Expression lhs = args.get(0);
- assert args.size() > 1 : runtimeNode + " must have two args";
- final Expression rhs = args.get(1);
-
- final Type type = runtimeNode.getType();
- final Symbol symbol = runtimeNode.getSymbol();
-
- switch (runtimeNode.getRequest()) {
- case EQ:
- case EQ_STRICT:
- return enterCmp(lhs, rhs, Condition.EQ, type, symbol);
- case NE:
- case NE_STRICT:
- return enterCmp(lhs, rhs, Condition.NE, type, symbol);
- case LE:
- return enterCmp(lhs, rhs, Condition.LE, type, symbol);
- case LT:
- return enterCmp(lhs, rhs, Condition.LT, type, symbol);
- case GE:
- return enterCmp(lhs, rhs, Condition.GE, type, symbol);
- case GT:
- return enterCmp(lhs, rhs, Condition.GT, type, symbol);
- case ADD:
- Type widest = Type.widest(lhs.getType(), rhs.getType());
- load(lhs, widest);
- load(rhs, widest);
- method.add();
- method.convert(type);
- method.store(symbol);
- return false;
- default:
- // it's ok to send this one on with only primitive arguments, maybe INSTANCEOF(true, true) or similar
- // assert false : runtimeNode + " has all primitive arguments. This is an inconsistent state";
- break;
- }
- }
-
- if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) {
- return false;
- }
-
- if (!runtimeNode.isFinal() && specializationCheck(runtimeNode.getRequest(), runtimeNode, args)) {
- return false;
+ private void loadRuntimeNode(final RuntimeNode runtimeNode) {
+ final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
+ if (nullCheck(runtimeNode, args)) {
+ return;
+ } else if(undefinedCheck(runtimeNode, args)) {
+ return;
}
-
- for (final Expression arg : args) {
- load(arg, Type.OBJECT);
+ // Revert a false undefined check to a strict equality check
+ final RuntimeNode newRuntimeNode;
+ final Request request = runtimeNode.getRequest();
+ if (Request.isUndefinedCheck(request)) {
+ newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT);
+ } else {
+ newRuntimeNode = runtimeNode;
}
- method.invokestatic(
- CompilerConstants.className(ScriptRuntime.class),
- runtimeNode.getRequest().toString(),
- new FunctionSignature(
- false,
- false,
- runtimeNode.getType(),
- args.size()).toString());
- method.convert(runtimeNode.getType());
- method.store(runtimeNode.getSymbol());
+ new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) {
+ @Override
+ void loadStack() {
+ for (final Expression arg : args) {
+ loadExpression(arg, TypeBounds.OBJECT);
+ }
+ }
+ @Override
+ void consumeStack() {
+ method.invokestatic(
+ CompilerConstants.className(ScriptRuntime.class),
+ newRuntimeNode.getRequest().toString(),
+ new FunctionSignature(
+ false,
+ false,
+ newRuntimeNode.getType(),
+ args.size()).toString());
+ }
+ }.emit();
- return false;
+ method.convert(newRuntimeNode.getType());
}
- @Override
- public boolean enterSplitNode(final SplitNode splitNode) {
- final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
+ private void defineCommonSplitMethodParameters() {
+ defineSplitMethodParameter(0, CALLEE);
+ defineSplitMethodParameter(1, THIS);
+ defineSplitMethodParameter(2, SCOPE);
+ }
- final FunctionNode fn = lc.getCurrentFunction();
- final String className = splitCompileUnit.getUnitClassName();
- final String name = splitNode.getName();
-
- final Class<?> rtype = fn.getReturnType().getTypeClass();
- final boolean needsArguments = fn.needsArguments();
- final Class<?>[] ptypes = needsArguments ?
- new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class, Object.class} :
- new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class};
-
- final MethodEmitter caller = method;
- unit = lc.pushCompileUnit(splitCompileUnit);
-
- final Call splitCall = staticCallNoLookup(
- className,
- name,
- methodDescriptor(rtype, ptypes));
-
- final MethodEmitter splitEmitter =
- splitCompileUnit.getClassEmitter().method(
- splitNode,
- name,
- rtype,
- ptypes);
-
- method = lc.pushMethodEmitter(splitEmitter);
- method.setFunctionNode(fn);
-
- assert fn.needsCallee() : "split function should require callee";
- caller.loadCompilerConstant(CALLEE);
- caller.loadCompilerConstant(THIS);
- caller.loadCompilerConstant(SCOPE);
- if (needsArguments) {
- caller.loadCompilerConstant(ARGUMENTS);
- }
- caller.invoke(splitCall);
- caller.storeCompilerConstant(RETURN);
-
- method.begin();
- // Copy scope to its target slot as first thing because the original slot could be used by return symbol.
- fixScopeSlot(fn);
-
- method.loadUndefined(fn.getReturnType());
- method.storeCompilerConstant(RETURN);
+ private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
+ defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
+ }
- return true;
+ private void defineSplitMethodParameter(final int slot, final Type type) {
+ method.defineBlockLocalVariable(slot, slot + type.getSlots());
+ method.onLocalStore(type, slot);
}
- private void fixScopeSlot(final FunctionNode functionNode) {
+ private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
// TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
- if (functionNode.compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
- method.load(Type.typeFor(ScriptObject.class), SCOPE.slot());
+ final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
+ final int defaultScopeSlot = SCOPE.slot();
+ int newExtraSlot = extraSlot;
+ if (actualScopeSlot != defaultScopeSlot) {
+ if (actualScopeSlot == extraSlot) {
+ newExtraSlot = extraSlot + 1;
+ method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
+ method.load(Type.OBJECT, extraSlot);
+ method.storeHidden(Type.OBJECT, newExtraSlot);
+ } else {
+ method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
+ }
+ method.load(SCOPE_TYPE, defaultScopeSlot);
method.storeCompilerConstant(SCOPE);
}
+ return newExtraSlot;
}
@Override
- public Node leaveSplitNode(final SplitNode splitNode) {
- assert method instanceof SplitMethodEmitter;
- final boolean hasReturn = method.hasReturn();
- final List<Label> targets = method.getExternalTargets();
-
- try {
- // Wrap up this method.
-
- method.loadCompilerConstant(RETURN);
- method._return(lc.getCurrentFunction().getReturnType());
- method.end();
-
- unit = lc.popCompileUnit(splitNode.getCompileUnit());
- method = lc.popMethodEmitter(method);
-
- } catch (final Throwable t) {
- Context.printStackTrace(t);
- final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + lc.getCurrentFunction().getSource().getName());
- e.initCause(t);
- throw e;
- }
-
- // Handle return from split method if there was one.
- final MethodEmitter caller = method;
- final int targetCount = targets.size();
-
- //no external jump targets or return in switch node
- if (!hasReturn && targets.isEmpty()) {
- return splitNode;
- }
-
- caller.loadCompilerConstant(SCOPE);
- caller.checkcast(Scope.class);
- caller.invoke(Scope.GET_SPLIT_STATE);
-
- final Label breakLabel = new Label("no_split_state");
- // Split state is -1 for no split state, 0 for return, 1..n+1 for break/continue
-
- //the common case is that we don't need a switch
- if (targetCount == 0) {
- assert hasReturn;
- caller.ifne(breakLabel);
- //has to be zero
- caller.label(new Label("split_return"));
- caller.loadCompilerConstant(RETURN);
- caller._return(lc.getCurrentFunction().getReturnType());
- caller.label(breakLabel);
- } else {
- assert !targets.isEmpty();
-
- final int low = hasReturn ? 0 : 1;
- final int labelCount = targetCount + 1 - low;
- final Label[] labels = new Label[labelCount];
-
- for (int i = 0; i < labelCount; i++) {
- labels[i] = new Label(i == 0 ? "split_return" : "split_" + targets.get(i - 1));
- }
- caller.tableswitch(low, targetCount, breakLabel, labels);
- for (int i = low; i <= targetCount; i++) {
- caller.label(labels[i - low]);
- if (i == 0) {
- caller.loadCompilerConstant(RETURN);
- caller._return(lc.getCurrentFunction().getReturnType());
- } else {
- // Clear split state.
- caller.loadCompilerConstant(SCOPE);
- caller.checkcast(Scope.class);
- caller.load(-1);
- caller.invoke(Scope.SET_SPLIT_STATE);
- caller.splitAwareGoto(lc, targets.get(i - 1));
- }
- }
- caller.label(breakLabel);
+ public boolean enterSplitReturn(final SplitReturn splitReturn) {
+ if (method.isReachable()) {
+ method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
}
+ return false;
+ }
- // If split has a return and caller is itself a split method it needs to propagate the return.
- if (hasReturn) {
- caller.setHasReturn();
+ @Override
+ public boolean enterSetSplitState(final SetSplitState setSplitState) {
+ if (method.isReachable()) {
+ method.setSplitState(setSplitState.getState());
}
-
- return splitNode;
+ return false;
}
@Override
public boolean enterSwitchNode(final SwitchNode switchNode) {
- lineNumber(switchNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(switchNode);
final Expression expression = switchNode.getExpression();
- final Symbol tag = switchNode.getTag();
- final boolean allInteger = tag.getSymbolType().isInteger();
final List<CaseNode> cases = switchNode.getCases();
- final CaseNode defaultCase = switchNode.getDefaultCase();
- final Label breakLabel = switchNode.getBreakLabel();
-
- Label defaultLabel = breakLabel;
- boolean hasDefault = false;
-
- if (defaultCase != null) {
- defaultLabel = defaultCase.getEntry();
- hasDefault = true;
- }
if (cases.isEmpty()) {
// still evaluate expression for side-effects.
- load(expression).pop();
- method.label(breakLabel);
+ loadAndDiscard(expression);
+ return false;
+ }
+
+ final CaseNode defaultCase = switchNode.getDefaultCase();
+ final Label breakLabel = switchNode.getBreakLabel();
+ final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
+
+ if (defaultCase != null && cases.size() == 1) {
+ // default case only
+ assert cases.get(0) == defaultCase;
+ loadAndDiscard(expression);
+ defaultCase.getBody().accept(this);
+ method.breakLabel(breakLabel, liveLocalsOnBreak);
return false;
}
- if (allInteger) {
+ // NOTE: it can still change in the tableswitch/lookupswitch case if there's no default case
+ // but we need to add a synthetic default case for local variable conversions
+ Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
+ final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
+
+ if (switchNode.isUniqueInteger()) {
// Tree for sorting values.
final TreeMap<Integer, Label> tree = new TreeMap<>();
@@ -1931,7 +2843,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final Label entry = caseNode.getEntry();
// Take first duplicate.
- if (!(tree.containsKey(value))) {
+ if (!tree.containsKey(value)) {
tree.put(value, entry);
}
}
@@ -1945,7 +2857,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// Discern low, high and range.
final int lo = values[0];
final int hi = values[size - 1];
- final int range = hi - lo + 1;
+ final long range = (long)hi - (long)lo + 1;
// Find an unused value for default.
int deflt = Integer.MIN_VALUE;
@@ -1958,7 +2870,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
// Load switch expression.
- load(expression);
+ loadExpressionUnbounded(expression);
final Type type = expression.getType();
// If expression not int see if we can convert, if not use deflt to trigger default.
@@ -1968,11 +2880,15 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.invoke(staticCallNoLookup(ScriptRuntime.class, "switchTagAsInt", int.class, exprClass.isPrimitive()? exprClass : Object.class, int.class));
}
- // If reasonable size and not too sparse (80%), use table otherwise use lookup.
- if (range > 0 && range < 4096 && range < (size * 5 / 4)) {
- final Label[] table = new Label[range];
+ if(hasSkipConversion) {
+ assert defaultLabel == breakLabel;
+ defaultLabel = new Label("switch_skip");
+ }
+ // TABLESWITCH needs (range + 3) 32-bit values; LOOKUPSWITCH needs ((size * 2) + 2). Choose the one with
+ // smaller representation, favor TABLESWITCH when they're equal size.
+ if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
+ final Label[] table = new Label[(int)range];
Arrays.fill(table, defaultLabel);
-
for (int i = 0; i < size; i++) {
final int value = values[i];
table[value - lo] = labels[i];
@@ -1987,97 +2903,163 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.lookupswitch(defaultLabel, ints, labels);
}
+ // This is a synthetic "default case" used in absence of actual default case, created if we need to apply
+ // local variable conversions if neither case is taken.
+ if(hasSkipConversion) {
+ method.label(defaultLabel);
+ method.beforeJoinPoint(switchNode);
+ method._goto(breakLabel);
+ }
} else {
- load(expression, Type.OBJECT);
- method.store(tag);
+ final Symbol tagSymbol = switchNode.getTag();
+ // TODO: we could have non-object tag
+ final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
+ loadExpressionAsObject(expression);
+ method.store(tagSymbol, Type.OBJECT);
for (final CaseNode caseNode : cases) {
final Expression test = caseNode.getTest();
if (test != null) {
- method.load(tag);
- load(test, Type.OBJECT);
+ method.load(Type.OBJECT, tagSlot);
+ loadExpressionAsObject(test);
method.invoke(ScriptRuntime.EQ_STRICT);
method.ifne(caseNode.getEntry());
}
}
- method._goto(hasDefault ? defaultLabel : breakLabel);
+ if (defaultCase != null) {
+ method._goto(defaultLabel);
+ } else {
+ method.beforeJoinPoint(switchNode);
+ method._goto(breakLabel);
+ }
}
+ // First case is only reachable through jump
+ assert !method.isReachable();
+
for (final CaseNode caseNode : cases) {
+ final Label fallThroughLabel;
+ if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
+ fallThroughLabel = new Label("fallthrough");
+ method._goto(fallThroughLabel);
+ } else {
+ fallThroughLabel = null;
+ }
method.label(caseNode.getEntry());
+ method.beforeJoinPoint(caseNode);
+ if(fallThroughLabel != null) {
+ method.label(fallThroughLabel);
+ }
caseNode.getBody().accept(this);
}
- if (!switchNode.isTerminal()) {
- method.label(breakLabel);
- }
+ method.breakLabel(breakLabel, liveLocalsOnBreak);
return false;
}
@Override
public boolean enterThrowNode(final ThrowNode throwNode) {
- lineNumber(throwNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(throwNode);
if (throwNode.isSyntheticRethrow()) {
+ method.beforeJoinPoint(throwNode);
+
//do not wrap whatever this is in an ecma exception, just rethrow it
- load(throwNode.getExpression());
+ final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
+ final Symbol exceptionSymbol = exceptionExpr.getSymbol();
+ method.load(exceptionSymbol, EXCEPTION_TYPE);
+ method.checkcast(EXCEPTION_TYPE.getTypeClass());
method.athrow();
return false;
}
- final Source source = lc.getCurrentFunction().getSource();
-
+ final Source source = getCurrentSource();
final Expression expression = throwNode.getExpression();
final int position = throwNode.position();
final int line = throwNode.getLineNumber();
final int column = source.getColumn(position);
- load(expression, Type.OBJECT);
+ // NOTE: we first evaluate the expression, and only after it was evaluated do we create the new ECMAException
+ // object and then somewhat cumbersomely move it beneath the evaluated expression on the stack. The reason for
+ // this is that if expression is optimistic (or contains an optimistic subexpression), we'd potentially access
+ // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
+ // verifier forbids that.
+ loadExpressionAsObject(expression);
method.load(source.getName());
method.load(line);
method.load(column);
method.invoke(ECMAException.CREATE);
+ method.beforeJoinPoint(throwNode);
method.athrow();
return false;
}
+ private Source getCurrentSource() {
+ return lc.getCurrentFunction().getSource();
+ }
+
@Override
public boolean enterTryNode(final TryNode tryNode) {
- lineNumber(tryNode);
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(tryNode);
final Block body = tryNode.getBody();
final List<Block> catchBlocks = tryNode.getCatchBlocks();
- final Symbol symbol = tryNode.getException();
+ final Symbol vmException = tryNode.getException();
final Label entry = new Label("try");
final Label recovery = new Label("catch");
- final Label exit = tryNode.getExit();
+ final Label exit = new Label("end_try");
final Label skip = new Label("skip");
+ method.canThrow(recovery);
+ // Effect any conversions that might be observed at the entry of the catch node before entering the try node.
+ // This is because even the first instruction in the try block must be presumed to be able to transfer control
+ // to the catch block. Note that this doesn't kill the original values; in this regard it works a lot like
+ // conversions of assignments within the try block.
+ method.beforeTry(tryNode, recovery);
method.label(entry);
-
- body.accept(this);
-
- if (!body.hasTerminalFlags()) {
- method._goto(skip);
+ catchLabels.push(recovery);
+ try {
+ body.accept(this);
+ } finally {
+ assert catchLabels.peek() == recovery;
+ catchLabels.pop();
}
method.label(exit);
+ final boolean bodyCanThrow = exit.isAfter(entry);
+ if(!bodyCanThrow) {
+ // The body can't throw an exception; don't even bother emitting the catch handlers, they're all dead code.
+ return false;
+ }
+
+ method._try(entry, exit, recovery, Throwable.class);
+ if (method.isReachable()) {
+ method._goto(skip);
+ }
method._catch(recovery);
- method.store(symbol);
+ method.store(vmException, EXCEPTION_TYPE);
- for (int i = 0; i < catchBlocks.size(); i++) {
+ final int catchBlockCount = catchBlocks.size();
+ final Label afterCatch = new Label("after_catch");
+ for (int i = 0; i < catchBlockCount; i++) {
+ assert method.isReachable();
final Block catchBlock = catchBlocks.get(i);
- //TODO this is very ugly - try not to call enter/leave methods directly
- //better to use the implicit lexical context scoping given by the visitor's
- //accept method.
+ // Because of the peculiarities of the flow control, we need to use an explicit push/enterBlock/leaveBlock
+ // here.
lc.push(catchBlock);
enterBlock(catchBlock);
@@ -2089,13 +3071,14 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
new Store<IdentNode>(exception) {
@Override
protected void storeNonDiscard() {
- return;
+ // This expression is neither part of a discard, nor needs to be left on the stack after it was
+ // stored, so we override storeNonDiscard to be a no-op.
}
@Override
protected void evaluate() {
if (catchNode.isSyntheticRethrow()) {
- method.load(symbol);
+ method.load(vmException, EXCEPTION_TYPE);
return;
}
/*
@@ -2104,126 +3087,273 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* caught object itself to the script catch var.
*/
final Label notEcmaException = new Label("no_ecma_exception");
- method.load(symbol).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
+ method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
method.checkcast(ECMAException.class); //TODO is this necessary?
method.getField(ECMAException.THROWN);
method.label(notEcmaException);
}
}.store();
- final Label next;
-
- if (exceptionCondition != null) {
- next = new Label("next");
- load(exceptionCondition, Type.BOOLEAN).ifeq(next);
+ final boolean isConditionalCatch = exceptionCondition != null;
+ final Label nextCatch;
+ if (isConditionalCatch) {
+ loadExpressionAsBoolean(exceptionCondition);
+ nextCatch = new Label("next_catch");
+ method.ifeq(nextCatch);
} else {
- next = null;
+ nextCatch = null;
}
catchBody.accept(this);
-
- if (i + 1 != catchBlocks.size() && !catchBody.hasTerminalFlags()) {
- method._goto(skip);
- }
-
- if (next != null) {
- if (i + 1 == catchBlocks.size()) {
- // no next catch block - rethrow if condition failed
- method._goto(skip);
- method.label(next);
- method.load(symbol).athrow();
- } else {
- method.label(next);
- }
- }
-
leaveBlock(catchBlock);
lc.pop(catchBlock);
+ if(method.isReachable()) {
+ method._goto(afterCatch);
+ }
+ if(nextCatch != null) {
+ method.label(nextCatch);
+ }
}
+ assert !method.isReachable();
+ // afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
+ method.label(afterCatch);
+ if(method.isReachable()) {
+ method.markDeadLocalVariable(vmException);
+ }
method.label(skip);
- method._try(entry, exit, recovery, Throwable.class);
// Finally body is always inlined elsewhere so it doesn't need to be emitted
-
return false;
}
@Override
public boolean enterVarNode(final VarNode varNode) {
-
- final Expression init = varNode.getInit();
-
- if (init == null) {
+ if(!method.isReachable()) {
return false;
}
-
- lineNumber(varNode);
-
+ final Expression init = varNode.getInit();
final IdentNode identNode = varNode.getName();
final Symbol identSymbol = identNode.getSymbol();
assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
+ final boolean needsScope = identSymbol.isScope();
+ if (init == null) {
+ if (needsScope && varNode.isBlockScoped()) {
+ // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
+ method.loadCompilerConstant(SCOPE);
+ method.loadUndefined(Type.OBJECT);
+ final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
+ assert isFastScope(identSymbol);
+ storeFastScopeVar(identSymbol, flags);
+ }
+ return false;
+ }
+
+ enterStatement(varNode);
assert method != null;
- final boolean needsScope = identSymbol.isScope();
if (needsScope) {
method.loadCompilerConstant(SCOPE);
}
if (needsScope) {
- load(init);
- int flags = CALLSITE_SCOPE | getCallSiteFlags();
+ loadExpressionUnbounded(init);
+ // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
+ final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
if (isFastScope(identSymbol)) {
storeFastScopeVar(identSymbol, flags);
} else {
- method.dynamicSet(identNode.getName(), flags);
+ method.dynamicSet(identNode.getName(), flags, false);
}
} else {
- load(init, identNode.getType());
- method.store(identSymbol);
+ final Type identType = identNode.getType();
+ if(identType == Type.UNDEFINED) {
+ // The initializer is either itself undefined (explicit assignment of undefined to undefined),
+ // or the left hand side is a dead variable.
+ assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
+ loadAndDiscard(init);
+ return false;
+ }
+ loadExpressionAsType(init, identType);
+ storeIdentWithCatchConversion(identNode, identType);
}
return false;
}
+ private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
+ // Assignments happening in try/catch blocks need to ensure that they also store a possibly wider typed value
+ // that will be live at the exit from the try block
+ final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
+ final Symbol symbol = identNode.getSymbol();
+ if(conversion != null && conversion.isLive()) {
+ assert symbol == conversion.getSymbol();
+ assert symbol.isBytecodeLocal();
+ // Only a single conversion from the target type to the join type is expected.
+ assert conversion.getNext() == null;
+ assert conversion.getFrom() == type;
+ // We must propagate potential type change to the catch block
+ final Label catchLabel = catchLabels.peek();
+ assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
+ assert catchLabel.isReachable();
+ final Type joinType = conversion.getTo();
+ final Label.Stack catchStack = catchLabel.getStack();
+ final int joinSlot = symbol.getSlot(joinType);
+ // With nested try/catch blocks (incl. synthetic ones for finally), we can have a supposed conversion for
+ // the exception symbol in the nested catch, but it isn't live in the outer catch block, so prevent doing
+ // conversions for it. E.g. in "try { try { ... } catch(e) { e = 1; } } catch(e2) { ... }", we must not
+ // introduce an I->O conversion on "e = 1" assignment as "e" is not live in "catch(e2)".
+ if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
+ method.dup();
+ method.convert(joinType);
+ method.store(symbol, joinType);
+ catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
+ method.canThrow(catchLabel);
+ // Store but keep the previous store live too.
+ method.store(symbol, type, false);
+ return;
+ }
+ }
+
+ method.store(symbol, type, true);
+ }
+
@Override
public boolean enterWhileNode(final WhileNode whileNode) {
- final Expression test = whileNode.getTest();
- final Block body = whileNode.getBody();
- final Label breakLabel = whileNode.getBreakLabel();
- final Label continueLabel = whileNode.getContinueLabel();
- final boolean isDoWhile = whileNode.isDoWhile();
- final Label loopLabel = new Label("loop");
-
- if (!isDoWhile) {
- method._goto(continueLabel);
+ if(!method.isReachable()) {
+ return false;
}
-
- method.label(loopLabel);
- body.accept(this);
- if (!whileNode.isTerminal()) {
- method.label(continueLabel);
- lineNumber(whileNode);
- new BranchOptimizer(this, method).execute(test, loopLabel, true);
- method.label(breakLabel);
+ if(whileNode.isDoWhile()) {
+ enterDoWhile(whileNode);
+ } else {
+ enterStatement(whileNode);
+ enterForOrWhile(whileNode, null);
}
-
return false;
}
- private void closeWith() {
- if (method.hasScope()) {
+ private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
+ // NOTE: the usual pattern for compiling test-first loops is "GOTO test; body; test; IFNE body". We use the less
+ // conventional "test; IFEQ break; body; GOTO test; break;". It has one extra unconditional GOTO in each repeat
+ // of the loop, but it's not a problem for modern JIT compilers. We do this because our local variable type
+ // tracking is unfortunately not really prepared for out-of-order execution, e.g. compiling the following
+ // contrived but legal JavaScript code snippet would fail because the test changes the type of "i" from object
+ // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
+ // Instead of adding more complexity to the local variable type tracking, we instead choose to emit this
+ // different code shape.
+ final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
+ final JoinPredecessorExpression test = loopNode.getTest();
+ if(Expression.isAlwaysFalse(test)) {
+ loadAndDiscard(test);
+ return;
+ }
+
+ method.beforeJoinPoint(loopNode);
+
+ final Label continueLabel = loopNode.getContinueLabel();
+ final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
+ method.label(repeatLabel);
+ final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();
+
+ final Block body = loopNode.getBody();
+ final Label breakLabel = loopNode.getBreakLabel();
+ final boolean testHasLiveConversion = test != null && LocalVariableConversion.hasLiveConversion(test);
+
+ if(Expression.isAlwaysTrue(test)) {
+ if(test != null) {
+ loadAndDiscard(test);
+ if(testHasLiveConversion) {
+ method.beforeJoinPoint(test);
+ }
+ }
+ } else if (test != null) {
+ if (testHasLiveConversion) {
+ emitBranch(test.getExpression(), body.getEntryLabel(), true);
+ method.beforeJoinPoint(test);
+ method._goto(breakLabel);
+ } else {
+ emitBranch(test.getExpression(), breakLabel, false);
+ }
+ }
+
+ body.accept(this);
+ if(repeatLabel != continueLabel) {
+ emitContinueLabel(continueLabel, liveLocalsOnContinue);
+ }
+
+ if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
+ // ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
method.loadCompilerConstant(SCOPE);
- method.invoke(ScriptRuntime.CLOSE_WITH);
+ method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
method.storeCompilerConstant(SCOPE);
}
+
+ if(method.isReachable()) {
+ if(modify != null) {
+ lineNumber(loopNode);
+ loadAndDiscard(modify);
+ method.beforeJoinPoint(modify);
+ }
+ method._goto(repeatLabel);
+ }
+
+ method.breakLabel(breakLabel, liveLocalsOnBreak);
+ }
+
+ private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
+ final boolean reachable = method.isReachable();
+ method.breakLabel(continueLabel, liveLocals);
+ // If we reach here only through a continue statement (e.g. body does not exit normally) then the
+ // continueLabel can have extra non-temp symbols (e.g. exception from a try/catch contained in the body). We
+ // must make sure those are thrown away.
+ if(!reachable) {
+ method.undefineLocalVariables(lc.getUsedSlotCount(), false);
+ }
}
+ private void enterDoWhile(final WhileNode whileNode) {
+ final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
+ method.beforeJoinPoint(whileNode);
+
+ final Block body = whileNode.getBody();
+ body.accept(this);
+
+ emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
+ if(method.isReachable()) {
+ lineNumber(whileNode);
+ final JoinPredecessorExpression test = whileNode.getTest();
+ final Label bodyEntryLabel = body.getEntryLabel();
+ final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
+ if(Expression.isAlwaysFalse(test)) {
+ loadAndDiscard(test);
+ if(testHasLiveConversion) {
+ method.beforeJoinPoint(test);
+ }
+ } else if(testHasLiveConversion) {
+ // If we have conversions after the test in do-while, they need to be effected on both branches.
+ final Label beforeExit = new Label("do_while_preexit");
+ emitBranch(test.getExpression(), beforeExit, false);
+ method.beforeJoinPoint(test);
+ method._goto(bodyEntryLabel);
+ method.label(beforeExit);
+ method.beforeJoinPoint(test);
+ } else {
+ emitBranch(test.getExpression(), bodyEntryLabel, true);
+ }
+ }
+ method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
+ }
+
+
@Override
public boolean enterWithNode(final WithNode withNode) {
+ if(!method.isReachable()) {
+ return false;
+ }
+ enterStatement(withNode);
final Expression expression = withNode.getExpression();
- final Node body = withNode.getBody();
+ final Block body = withNode.getBody();
// It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's
// pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the
@@ -2231,28 +3361,26 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// for its side effect and visit the body, and not bother opening and closing a WithObject.
final boolean hasScope = method.hasScope();
- final Label tryLabel;
if (hasScope) {
- tryLabel = new Label("with_try");
- method.label(tryLabel);
method.loadCompilerConstant(SCOPE);
- } else {
- tryLabel = null;
}
- load(expression, Type.OBJECT);
+ loadExpressionAsObject(expression);
+ final Label tryLabel;
if (hasScope) {
// Construct a WithObject if we have a scope
method.invoke(ScriptRuntime.OPEN_WITH);
method.storeCompilerConstant(SCOPE);
+ tryLabel = new Label("with_try");
+ method.label(tryLabel);
} else {
// We just loaded the expression for its side effect and to check
// for null or undefined value.
globalCheckObjectCoercible();
+ tryLabel = null;
}
-
// Always process body
body.accept(this);
@@ -2262,62 +3390,78 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final Label catchLabel = new Label("with_catch");
final Label exitLabel = new Label("with_exit");
- if (!body.isTerminal()) {
- closeWith();
- method._goto(exitLabel);
- }
-
method.label(endLabel);
+ // Somewhat conservatively presume that if the body is not empty, it can throw an exception. In any case,
+ // we must prevent trying to emit a try-catch for empty range, as it causes a verification error.
+ final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
+ if(bodyCanThrow) {
+ method._try(tryLabel, endLabel, catchLabel);
+ }
- method._catch(catchLabel);
- closeWith();
- method.athrow();
-
- method.label(exitLabel);
+ final boolean reachable = method.isReachable();
+ if(reachable) {
+ popScope();
+ if(bodyCanThrow) {
+ method._goto(exitLabel);
+ }
+ }
- method._try(tryLabel, endLabel, catchLabel);
+ if(bodyCanThrow) {
+ method._catch(catchLabel);
+ popScopeException();
+ method.athrow();
+ if(reachable) {
+ method.label(exitLabel);
+ }
+ }
}
return false;
}
- @Override
- public boolean enterADD(final UnaryNode unaryNode) {
- load(unaryNode.rhs(), unaryNode.getType());
- assert unaryNode.getType().isNumeric();
- method.store(unaryNode.getSymbol());
- return false;
+ private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+ loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
+ if(method.peekType() == Type.BOOLEAN) {
+ // It's a no-op in bytecode, but we must make sure it is treated as an int for purposes of type signatures
+ method.convert(Type.INT);
+ }
}
- @Override
- public boolean enterBIT_NOT(final UnaryNode unaryNode) {
- load(unaryNode.rhs(), Type.INT).load(-1).xor().store(unaryNode.getSymbol());
- return false;
+ private void loadBIT_NOT(final UnaryNode unaryNode) {
+ loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
}
- @Override
- public boolean enterDECINC(final UnaryNode unaryNode) {
- final Expression rhs = unaryNode.rhs();
+ private void loadDECINC(final UnaryNode unaryNode) {
+ final Expression operand = unaryNode.getExpression();
final Type type = unaryNode.getType();
+ final TypeBounds typeBounds = new TypeBounds(type, Type.NUMBER);
final TokenType tokenType = unaryNode.tokenType();
final boolean isPostfix = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
final boolean isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
assert !type.isObject();
- new SelfModifyingStore<UnaryNode>(unaryNode, rhs) {
+ new SelfModifyingStore<UnaryNode>(unaryNode, operand) {
+
+ private void loadRhs() {
+ loadExpression(operand, typeBounds, true);
+ }
@Override
protected void evaluate() {
- load(rhs, type, true);
- if (!isPostfix) {
- if (type.isInteger()) {
- method.load(isIncrement ? 1 : -1);
- } else if (type.isLong()) {
- method.load(isIncrement ? 1L : -1L);
- } else {
- method.load(isIncrement ? 1.0 : -1.0);
- }
- method.add();
+ if(isPostfix) {
+ loadRhs();
+ } else {
+ new OptimisticOperation(unaryNode, typeBounds) {
+ @Override
+ void loadStack() {
+ loadRhs();
+ loadMinusOne();
+ }
+ @Override
+ void consumeStack() {
+ doDecInc(getProgramPoint());
+ }
+ }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
}
}
@@ -2325,448 +3469,485 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
protected void storeNonDiscard() {
super.storeNonDiscard();
if (isPostfix) {
- if (type.isInteger()) {
- method.load(isIncrement ? 1 : -1);
- } else if (type.isLong()) {
- method.load(isIncrement ? 1L : 1L);
- } else {
- method.load(isIncrement ? 1.0 : -1.0);
- }
- method.add();
+ new OptimisticOperation(unaryNode, typeBounds) {
+ @Override
+ void loadStack() {
+ loadMinusOne();
+ }
+ @Override
+ void consumeStack() {
+ doDecInc(getProgramPoint());
+ }
+ }.emit(1); // 1 for non-incremented result on the top of the stack pushed in evaluate()
}
}
- }.store();
- return false;
+ private void loadMinusOne() {
+ if (type.isInteger()) {
+ method.load(isIncrement ? 1 : -1);
+ } else if (type.isLong()) {
+ method.load(isIncrement ? 1L : -1L);
+ } else {
+ method.load(isIncrement ? 1.0 : -1.0);
+ }
+ }
+
+ private void doDecInc(final int programPoint) {
+ method.add(programPoint);
+ }
+ }.store();
}
- @Override
- public boolean enterDISCARD(final UnaryNode unaryNode) {
- final Expression rhs = unaryNode.rhs();
+ private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
+ return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
+ }
- lc.pushDiscard(rhs);
- load(rhs);
+ private void loadAndDiscard(final Expression expr) {
+ // TODO: move checks for discarding to actual expression load code (e.g. as we do with void). That way we might
+ // be able to eliminate even more checks.
+ if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
+ assert lc.getCurrentDiscard() != expr;
+ // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating
+ // undefined.
+ return;
+ }
- if (lc.getCurrentDiscard() == rhs) {
- assert !rhs.isAssignment();
+ lc.pushDiscard(expr);
+ loadExpression(expr, TypeBounds.UNBOUNDED);
+ if (lc.getCurrentDiscard() == expr) {
+ assert !expr.isAssignment();
+ // NOTE: if we had a way to load with type void, we could avoid popping
method.pop();
lc.popDiscard();
}
-
- return false;
}
- @Override
- public boolean enterNEW(final UnaryNode unaryNode) {
- final CallNode callNode = (CallNode)unaryNode.rhs();
+ private void loadNEW(final UnaryNode unaryNode) {
+ final CallNode callNode = (CallNode)unaryNode.getExpression();
final List<Expression> args = callNode.getArgs();
// Load function reference.
- load(callNode.getFunction(), Type.OBJECT); // must detect type error
+ loadExpressionAsObject(callNode.getFunction()); // must detect type error
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
- method.store(unaryNode.getSymbol());
-
- return false;
- }
-
- @Override
- public boolean enterNOT(final UnaryNode unaryNode) {
- final Expression rhs = unaryNode.rhs();
-
- load(rhs, Type.BOOLEAN);
-
- final Label trueLabel = new Label("true");
- final Label afterLabel = new Label("after");
-
- method.ifne(trueLabel);
- method.load(true);
- method._goto(afterLabel);
- method.label(trueLabel);
- method.load(false);
- method.label(afterLabel);
- method.store(unaryNode.getSymbol());
-
- return false;
- }
-
- @Override
- public boolean enterSUB(final UnaryNode unaryNode) {
- assert unaryNode.getType().isNumeric();
- load(unaryNode.rhs(), unaryNode.getType()).neg().store(unaryNode.getSymbol());
- return false;
}
- @Override
- public boolean enterVOID(final UnaryNode unaryNode) {
- load(unaryNode.rhs()).pop();
- method.loadUndefined(Type.OBJECT);
+ private void loadNOT(final UnaryNode unaryNode) {
+ final Expression expr = unaryNode.getExpression();
+ if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
+ // !!x is idiomatic boolean cast in JavaScript
+ loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
+ } else {
+ final Label trueLabel = new Label("true");
+ final Label afterLabel = new Label("after");
- return false;
+ emitBranch(expr, trueLabel, true);
+ method.load(true);
+ method._goto(afterLabel);
+ method.label(trueLabel);
+ method.load(false);
+ method.label(afterLabel);
+ }
}
- private void enterNumericAdd(final Expression lhs, final Expression rhs, final Type type, final Symbol symbol) {
- loadBinaryOperands(lhs, rhs, type);
- method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
- method.store(symbol);
+ private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+ final Type type = unaryNode.getType();
+ assert type.isNumeric();
+ final TypeBounds numericBounds = resultBounds.booleanToInt();
+ new OptimisticOperation(unaryNode, numericBounds) {
+ @Override
+ void loadStack() {
+ final Expression expr = unaryNode.getExpression();
+ loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
+ }
+ @Override
+ void consumeStack() {
+ // Must do an explicit conversion to the operation's type when it's double so that we correctly handle
+ // negation of an int 0 to a double -0. With this, we get the correct negation of a local variable after
+ // it deoptimized, e.g. "iload_2; i2d; dneg". Without this, we get "iload_2; ineg; i2d".
+ if(type.isNumber()) {
+ method.convert(type);
+ }
+ method.neg(getProgramPoint());
+ }
+ }.emit();
}
- @Override
- public boolean enterADD(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
-
- final Type type = binaryNode.getType();
- if (type.isNumeric()) {
- enterNumericAdd(lhs, rhs, type, binaryNode.getSymbol());
+ public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+ loadAndDiscard(unaryNode.getExpression());
+ if(lc.getCurrentDiscard() == unaryNode) {
+ lc.popDiscard();
} else {
- loadBinaryOperands(binaryNode);
- method.add();
- method.store(binaryNode.getSymbol());
+ method.loadUndefined(resultBounds.widest);
}
+ }
- return false;
+ public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+ new OptimisticOperation(binaryNode, resultBounds) {
+ @Override
+ void loadStack() {
+ final TypeBounds operandBounds;
+ final boolean isOptimistic = isValid(getProgramPoint());
+ boolean forceConversionSeparation = false;
+ if(isOptimistic) {
+ operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
+ } else {
+ // Non-optimistic, non-FP +. Allow it to overflow.
+ final Type widestOperationType = binaryNode.getWidestOperationType();
+ operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
+ forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
+ }
+ loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
+ }
+
+ @Override
+ void consumeStack() {
+ method.add(getProgramPoint());
+ }
+ }.emit();
}
- private boolean enterAND_OR(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
+ private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
+ final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
final Label skip = new Label("skip");
+ if(narrowestOperandType == Type.BOOLEAN) {
+ // optimize all-boolean logical expressions
+ final Label onTrue = new Label("andor_true");
+ emitBranch(binaryNode, onTrue, true);
+ method.load(false);
+ method._goto(skip);
+ method.label(onTrue);
+ method.load(true);
+ method.label(skip);
+ return;
+ }
- load(lhs, Type.OBJECT).dup().convert(Type.BOOLEAN);
+ final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
+ final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
+ final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
+ final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
- if (binaryNode.tokenType() == TokenType.AND) {
- method.ifeq(skip);
+ loadExpression(lhs, outBounds).dup().convert(Type.BOOLEAN);
+ if (isAnd) {
+ if(lhsConvert) {
+ method.ifne(evalRhs);
+ } else {
+ method.ifeq(skip);
+ }
+ } else if(lhsConvert) {
+ method.ifeq(evalRhs);
} else {
method.ifne(skip);
}
+ if(lhsConvert) {
+ method.beforeJoinPoint(lhs);
+ method._goto(skip);
+ method.label(evalRhs);
+ }
+
method.pop();
- load(rhs, Type.OBJECT);
+ final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
+ loadExpression(rhs, outBounds);
+ method.beforeJoinPoint(rhs);
method.label(skip);
- method.store(binaryNode.getSymbol());
+ }
- return false;
+ private static boolean isLocalVariable(final Expression lhs) {
+ return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
}
- @Override
- public boolean enterAND(final BinaryNode binaryNode) {
- return enterAND_OR(binaryNode);
+ private static boolean isLocalVariable(final IdentNode lhs) {
+ return lhs.getSymbol().isBytecodeLocal();
}
- @Override
- public boolean enterASSIGN(final BinaryNode binaryNode) {
+ // NOTE: does not use resultBounds as the assignment is driven by the type of the RHS
+ private void loadASSIGN(final BinaryNode binaryNode) {
final Expression lhs = binaryNode.lhs();
final Expression rhs = binaryNode.rhs();
- final Type lhsType = lhs.getType();
final Type rhsType = rhs.getType();
-
- if (!lhsType.isEquivalentTo(rhsType)) {
- //this is OK if scoped, only locals are wrong
+ // Detect dead assignments
+ if(lhs instanceof IdentNode) {
+ final Symbol symbol = ((IdentNode)lhs).getSymbol();
+ if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.getCurrentDiscard() == binaryNode) {
+ loadAndDiscard(rhs);
+ lc.popDiscard();
+ method.markDeadLocalVariable(symbol);
+ return;
+ }
}
new Store<BinaryNode>(binaryNode, lhs) {
@Override
protected void evaluate() {
- if ((lhs instanceof IdentNode) && !lhs.getSymbol().isScope()) {
- load(rhs, lhsType);
- } else {
- load(rhs);
- }
+ // NOTE: we're loading with "at least as wide as" so optimistic operations on the right hand side
+ // remain optimistic, and then explicitly convert to the required type if needed.
+ loadExpressionAsType(rhs, rhsType);
}
}.store();
-
- return false;
}
/**
- * Helper class for assignment ops, e.g. *=, += and so on..
+ * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
*/
- private abstract class AssignOp extends SelfModifyingStore<BinaryNode> {
-
- /** The type of the resulting operation */
- private final Type opType;
+ private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {
/**
* Constructor
*
* @param node the assign op node
*/
- AssignOp(final BinaryNode node) {
- this(node.getType(), node);
- }
-
- /**
- * Constructor
- *
- * @param opType type of the computation - overriding the type of the node
- * @param node the assign op node
- */
- AssignOp(final Type opType, final BinaryNode node) {
+ BinaryOptimisticSelfAssignment(final BinaryNode node) {
super(node, node.lhs());
- this.opType = opType;
}
- protected abstract void op();
+ protected abstract void op(OptimisticOperation oo);
@Override
protected void evaluate() {
- loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), opType, true);
- op();
+ final Expression lhs = assignNode.lhs();
+ final Expression rhs = assignNode.rhs();
+ final Type widestOperationType = assignNode.getWidestOperationType();
+ final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
+ new OptimisticOperation(assignNode, bounds) {
+ @Override
+ void loadStack() {
+ final boolean forceConversionSeparation;
+ if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
+ forceConversionSeparation = false;
+ } else {
+ final Type operandType = Type.widest(booleanToInt(objectToNumber(lhs.getType())), booleanToInt(objectToNumber(rhs.getType())));
+ forceConversionSeparation = operandType.narrowerThan(widestOperationType);
+ }
+ loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
+ }
+ @Override
+ void consumeStack() {
+ op(this);
+ }
+ }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
method.convert(assignNode.getType());
}
}
- @Override
- public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
- assert RuntimeNode.Request.ADD.canSpecialize();
- final Type lhsType = binaryNode.lhs().getType();
- final Type rhsType = binaryNode.rhs().getType();
- final boolean specialize = binaryNode.getType() == Type.OBJECT;
+ /**
+ * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
+ */
+ private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
+ BinarySelfAssignment(final BinaryNode node) {
+ super(node, node.lhs());
+ }
- new AssignOp(binaryNode) {
+ protected abstract void op();
- @Override
- protected void op() {
- if (specialize) {
- method.dynamicRuntimeCall(
- new SpecializedRuntimeNode(
- Request.ADD,
- new Type[] {
- lhsType,
- rhsType,
- },
- Type.OBJECT).getInitialName(),
- Type.OBJECT,
- Request.ADD);
- } else {
- method.add();
- }
- }
+ @Override
+ protected void evaluate() {
+ loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
+ op();
+ }
+ }
+ private void loadASSIGN_ADD(final BinaryNode binaryNode) {
+ new BinaryOptimisticSelfAssignment(binaryNode) {
@Override
- protected void evaluate() {
- super.evaluate();
+ protected void op(final OptimisticOperation oo) {
+ assert !(binaryNode.getType().isObject() && oo.isOptimistic);
+ method.add(oo.getProgramPoint());
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
method.and();
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
method.or();
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
method.xor();
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
- new AssignOp(binaryNode) {
+ private void loadASSIGN_DIV(final BinaryNode binaryNode) {
+ new BinaryOptimisticSelfAssignment(binaryNode) {
@Override
- protected void op() {
- method.div();
+ protected void op(final OptimisticOperation oo) {
+ method.div(oo.getProgramPoint());
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
- new AssignOp(binaryNode) {
+ private void loadASSIGN_MOD(final BinaryNode binaryNode) {
+ new BinaryOptimisticSelfAssignment(binaryNode) {
@Override
- protected void op() {
- method.rem();
+ protected void op(final OptimisticOperation oo) {
+ method.rem(oo.getProgramPoint());
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
- new AssignOp(binaryNode) {
+ private void loadASSIGN_MUL(final BinaryNode binaryNode) {
+ new BinaryOptimisticSelfAssignment(binaryNode) {
@Override
- protected void op() {
- method.mul();
+ protected void op(final OptimisticOperation oo) {
+ method.mul(oo.getProgramPoint());
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_SAR(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
method.sar();
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_SHL(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
method.shl();
}
}.store();
-
- return false;
}
- @Override
- public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
- new AssignOp(Type.INT, binaryNode) {
+ private void loadASSIGN_SHR(final BinaryNode binaryNode) {
+ new BinarySelfAssignment(binaryNode) {
@Override
protected void op() {
- method.shr();
- method.convert(Type.LONG).load(JSType.MAX_UINT).and();
+ doSHR();
}
+
}.store();
+ }
- return false;
+ private void doSHR() {
+ // TODO: make SHR optimistic
+ method.shr();
+ toUint();
}
- @Override
- public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
- new AssignOp(binaryNode) {
+ private void toUint() {
+ JSType.TO_UINT32_I.invoke(method);
+ }
+
+ private void loadASSIGN_SUB(final BinaryNode binaryNode) {
+ new BinaryOptimisticSelfAssignment(binaryNode) {
@Override
- protected void op() {
- method.sub();
+ protected void op(final OptimisticOperation oo) {
+ method.sub(oo.getProgramPoint());
}
}.store();
-
- return false;
}
/**
* Helper class for binary arithmetic ops
*/
private abstract class BinaryArith {
+ protected abstract void op(int programPoint);
- protected abstract void op();
+ protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
+ final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
+ new OptimisticOperation(node, numericBounds) {
+ @Override
+ void loadStack() {
+ final TypeBounds operandBounds;
+ boolean forceConversionSeparation = false;
+ if(numericBounds.narrowest == Type.NUMBER) {
+ // Result should be double always. Propagate it into the operands so we don't have lots of I2D
+ // and L2D after operand evaluation.
+ assert numericBounds.widest == Type.NUMBER;
+ operandBounds = numericBounds;
+ } else {
+ final boolean isOptimistic = isValid(getProgramPoint());
+ if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
+ operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
+ } else {
+ // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
+ operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
+ numericBounds.widest), Type.NUMBER);
+ forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest);
+ }
+ }
+ loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
+ }
- protected void evaluate(final BinaryNode node) {
- loadBinaryOperands(node);
- op();
- method.store(node.getSymbol());
+ @Override
+ void consumeStack() {
+ op(getProgramPoint());
+ }
+ }.emit();
}
}
- @Override
- public boolean enterBIT_AND(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void op() {
- method.and();
- }
- }.evaluate(binaryNode);
-
- return false;
+ private void loadBIT_AND(final BinaryNode binaryNode) {
+ loadBinaryOperands(binaryNode);
+ method.and();
}
- @Override
- public boolean enterBIT_OR(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void op() {
- method.or();
- }
- }.evaluate(binaryNode);
-
- return false;
- }
-
- @Override
- public boolean enterBIT_XOR(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void op() {
- method.xor();
- }
- }.evaluate(binaryNode);
-
- return false;
+ private void loadBIT_OR(final BinaryNode binaryNode) {
+ // Optimize x|0 to (int)x
+ if (isRhsZero(binaryNode)) {
+ loadExpressionAsType(binaryNode.lhs(), Type.INT);
+ } else {
+ loadBinaryOperands(binaryNode);
+ method.or();
+ }
}
- private boolean enterComma(final BinaryNode binaryNode) {
- final Expression lhs = binaryNode.lhs();
+ private static boolean isRhsZero(final BinaryNode binaryNode) {
final Expression rhs = binaryNode.rhs();
+ return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
+ }
- load(lhs);
- load(rhs);
- method.store(binaryNode.getSymbol());
-
- return false;
+ private void loadBIT_XOR(final BinaryNode binaryNode) {
+ loadBinaryOperands(binaryNode);
+ method.xor();
}
- @Override
- public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
- return enterComma(binaryNode);
+ private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+ loadAndDiscard(binaryNode.lhs());
+ loadExpression(binaryNode.rhs(), resultBounds);
}
- @Override
- public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
- return enterComma(binaryNode);
+ private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+ loadExpression(binaryNode.lhs(), resultBounds);
+ loadAndDiscard(binaryNode.rhs());
}
- @Override
- public boolean enterDIV(final BinaryNode binaryNode) {
+ private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
new BinaryArith() {
@Override
- protected void op() {
- method.div();
+ protected void op(final int programPoint) {
+ method.div(programPoint);
}
- }.evaluate(binaryNode);
-
- return false;
+ }.evaluate(binaryNode, resultBounds);
}
- private boolean enterCmp(final Expression lhs, final Expression rhs, final Condition cond, final Type type, final Symbol symbol) {
- final Type lhsType = lhs.getType();
- final Type rhsType = rhs.getType();
+ private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
+ assert comparisonOperandsArePrimitive(binaryNode) : binaryNode;
+ loadBinaryOperands(binaryNode);
- final Type widest = Type.widest(lhsType, rhsType);
- assert widest.isNumeric() || widest.isBoolean() : widest;
-
- loadBinaryOperands(lhs, rhs, widest);
final Label trueLabel = new Label("trueLabel");
final Label afterLabel = new Label("skip");
@@ -2777,177 +3958,100 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.label(trueLabel);
method.load(Boolean.TRUE);
method.label(afterLabel);
-
- method.convert(type);
- method.store(symbol);
-
- return false;
- }
-
- private boolean enterCmp(final BinaryNode binaryNode, final Condition cond) {
- return enterCmp(binaryNode.lhs(), binaryNode.rhs(), cond, binaryNode.getType(), binaryNode.getSymbol());
- }
-
- @Override
- public boolean enterEQ(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.EQ);
- }
-
- @Override
- public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.EQ);
- }
-
- @Override
- public boolean enterGE(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.GE);
}
- @Override
- public boolean enterGT(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.GT);
+ private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) {
+ final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
+ return widest.isNumeric() || widest.isBoolean();
}
- @Override
- public boolean enterLE(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.LE);
- }
-
- @Override
- public boolean enterLT(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.LT);
- }
-
- @Override
- public boolean enterMOD(final BinaryNode binaryNode) {
+ private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
new BinaryArith() {
@Override
- protected void op() {
- method.rem();
+ protected void op(final int programPoint) {
+ method.rem(programPoint);
}
- }.evaluate(binaryNode);
-
- return false;
+ }.evaluate(binaryNode, resultBounds);
}
- @Override
- public boolean enterMUL(final BinaryNode binaryNode) {
+ private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
new BinaryArith() {
@Override
- protected void op() {
- method.mul();
+ protected void op(final int programPoint) {
+ method.mul(programPoint);
}
- }.evaluate(binaryNode);
-
- return false;
+ }.evaluate(binaryNode, resultBounds);
}
- @Override
- public boolean enterNE(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.NE);
+ private void loadSAR(final BinaryNode binaryNode) {
+ loadBinaryOperands(binaryNode);
+ method.sar();
}
- @Override
- public boolean enterNE_STRICT(final BinaryNode binaryNode) {
- return enterCmp(binaryNode, Condition.NE);
+ private void loadSHL(final BinaryNode binaryNode) {
+ loadBinaryOperands(binaryNode);
+ method.shl();
}
- @Override
- public boolean enterOR(final BinaryNode binaryNode) {
- return enterAND_OR(binaryNode);
+ private void loadSHR(final BinaryNode binaryNode) {
+ // Optimize x >>> 0 to (uint)x
+ if (isRhsZero(binaryNode)) {
+ loadExpressionAsType(binaryNode.lhs(), Type.INT);
+ toUint();
+ } else {
+ loadBinaryOperands(binaryNode);
+ doSHR();
+ }
}
- @Override
- public boolean enterSAR(final BinaryNode binaryNode) {
+ private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
new BinaryArith() {
@Override
- protected void op() {
- method.sar();
+ protected void op(final int programPoint) {
+ method.sub(programPoint);
}
- }.evaluate(binaryNode);
-
- return false;
+ }.evaluate(binaryNode, resultBounds);
}
@Override
- public boolean enterSHL(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void op() {
- method.shl();
- }
- }.evaluate(binaryNode);
-
- return false;
+ public boolean enterLabelNode(final LabelNode labelNode) {
+ labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
+ return true;
}
@Override
- public boolean enterSHR(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void evaluate(final BinaryNode node) {
- loadBinaryOperands(node.lhs(), node.rhs(), Type.INT);
- op();
- method.store(node.getSymbol());
- }
- @Override
- protected void op() {
- method.shr();
- method.convert(Type.LONG).load(JSType.MAX_UINT).and();
- }
- }.evaluate(binaryNode);
-
- return false;
+ protected boolean enterDefault(final Node node) {
+ throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
}
- @Override
- public boolean enterSUB(final BinaryNode binaryNode) {
- new BinaryArith() {
- @Override
- protected void op() {
- method.sub();
- }
- }.evaluate(binaryNode);
+ private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
+ final Expression test = ternaryNode.getTest();
+ final JoinPredecessorExpression trueExpr = ternaryNode.getTrueExpression();
+ final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();
- return false;
- }
+ final Label falseLabel = new Label("ternary_false");
+ final Label exitLabel = new Label("ternary_exit");
- @Override
- public boolean enterTernaryNode(final TernaryNode ternaryNode) {
- final Expression test = ternaryNode.getTest();
- final Expression trueExpr = ternaryNode.getTrueExpression();
- final Expression falseExpr = ternaryNode.getFalseExpression();
-
- final Symbol symbol = ternaryNode.getSymbol();
- final Label falseLabel = new Label("ternary_false");
- final Label exitLabel = new Label("ternary_exit");
-
- Type widest = Type.widest(ternaryNode.getType(), Type.widest(trueExpr.getType(), falseExpr.getType()));
- if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
- widest = Type.OBJECT;
- }
-
- load(test, Type.BOOLEAN);
- // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
- // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
- // symmetry for the temporary slot for this TernaryNode. This is evidence that we assign types and explicit conversions
- // too early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
- // do this property. Then we never need any conversions in CodeGenerator
- method.ifeq(falseLabel);
- load(trueExpr, widest);
+ final Type outNarrowest = Type.narrowest(resultBounds.widest, Type.generic(Type.widestReturnType(trueExpr.getType(), falseExpr.getType())));
+ final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);
+
+ emitBranch(test, falseLabel, false);
+
+ loadExpression(trueExpr.getExpression(), outBounds);
+ assert Type.generic(method.peekType()) == outBounds.narrowest;
+ method.beforeJoinPoint(trueExpr);
method._goto(exitLabel);
method.label(falseLabel);
- load(falseExpr, widest);
+ loadExpression(falseExpr.getExpression(), outBounds);
+ assert Type.generic(method.peekType()) == outBounds.narrowest;
+ method.beforeJoinPoint(falseExpr);
method.label(exitLabel);
- method.store(symbol);
-
- return false;
}
/**
* Generate all shared scope calls generated during codegen.
*/
- protected void generateScopeCalls() {
+ void generateScopeCalls() {
for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
scopeAccess.generateScopeCall();
}
@@ -2957,20 +4061,18 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* Debug code used to print symbols
*
* @param block the block we are in
+ * @param function the function we are in
* @param ident identifier for block or function where applicable
*/
- @SuppressWarnings("resource")
- private void printSymbols(final Block block, final String ident) {
- if (!compiler.getEnv()._print_symbols) {
- return;
- }
-
- final PrintWriter out = compiler.getEnv().getErr();
- out.println("[BLOCK in '" + ident + "']");
- if (!block.printSymbols(out)) {
- out.println("<no symbols>");
+ private void printSymbols(final Block block, final FunctionNode function, final String ident) {
+ if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
+ final PrintWriter out = compiler.getScriptEnvironment().getErr();
+ out.println("[BLOCK in '" + ident + "']");
+ if (!block.printSymbols(out)) {
+ out.println("<no symbols>");
+ }
+ out.println();
}
- out.println();
}
@@ -3015,7 +4117,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private int depth;
/** If we have too many arguments, we need temporary storage, this is stored in 'quick' */
- private Symbol quick;
+ private IdentNode quick;
/**
* Constructor
@@ -3046,9 +4148,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
private void prologue() {
- final Symbol targetSymbol = target.getSymbol();
- final Symbol scopeSymbol = lc.getCurrentFunction().compilerConstant(SCOPE);
-
/**
* This loads the parts of the target, e.g base and index. they are kept
* on the stack throughout the store and used at the end to execute it
@@ -3057,9 +4156,10 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterIdentNode(final IdentNode node) {
- if (targetSymbol.isScope()) {
- method.load(scopeSymbol);
- depth++;
+ if (node.getSymbol().isScope()) {
+ method.loadCompilerConstant(SCOPE);
+ depth += Type.SCOPE.getSlots();
+ assert depth == 1;
}
return false;
}
@@ -3069,8 +4169,9 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final BaseNode baseNode = (BaseNode)target;
final Expression base = baseNode.getBase();
- load(base, Type.OBJECT);
+ loadExpressionAsObject(base);
depth += Type.OBJECT.getSlots();
+ assert depth == 1;
if (isSelfModifying()) {
method.dup();
@@ -3090,9 +4191,9 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final Expression index = node.getIndex();
if (!index.getType().isNumeric()) {
// could be boolean here as well
- load(index, Type.OBJECT);
+ loadExpressionAsObject(index);
} else {
- load(index);
+ loadExpressionUnbounded(index);
}
depth += index.getType().getSlots();
@@ -3107,28 +4208,23 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
});
}
- private Symbol quickSymbol(final Type type) {
- return quickSymbol(type, QUICK_PREFIX.symbolName());
- }
-
/**
- * Quick symbol generates an extra local variable, always using the same
- * slot, one that is available after the end of the frame.
+ * Generates an extra local variable, always using the same slot, one that is available after the end of the
+ * frame.
*
- * @param type the type of the symbol
- * @param prefix the prefix for the variable name for the symbol
+ * @param type the type of the variable
*
- * @return the quick symbol
+ * @return the quick variable
*/
- private Symbol quickSymbol(final Type type, final String prefix) {
- final String name = lc.getCurrentFunction().uniqueName(prefix);
- final Symbol symbol = new Symbol(name, IS_TEMP | IS_INTERNAL);
-
- symbol.setType(type);
+ private IdentNode quickLocalVariable(final Type type) {
+ final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
+ final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
+ symbol.setHasSlotFor(type);
+ symbol.setFirstSlot(lc.quickSlot(type));
- symbol.setSlot(lc.quickSlot(symbol));
+ final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);
- return symbol;
+ return quickIdent;
}
// store the result that "lives on" after the op, e.g. "i" in i++ postfix.
@@ -3139,16 +4235,12 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return;
}
- final Symbol symbol = assignNode.getSymbol();
- if (symbol.hasSlot()) {
- method.dup().store(symbol);
- return;
- }
-
if (method.dup(depth) == null) {
method.dup();
- this.quick = quickSymbol(method.peekType());
- method.store(quick);
+ final Type quickType = method.peekType();
+ this.quick = quickLocalVariable(quickType);
+ final Symbol quickSymbol = quick.getSymbol();
+ method.storeTemp(quickType, quickSymbol.getFirstSlot());
}
}
@@ -3163,7 +4255,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
*/
target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
- protected boolean enterDefault(Node node) {
+ protected boolean enterDefault(final Node node) {
throw new AssertionError("Unexpected node " + node + " in store epilogue");
}
@@ -3172,14 +4264,20 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final Symbol symbol = node.getSymbol();
assert symbol != null;
if (symbol.isScope()) {
+ final int flags = CALLSITE_SCOPE | getCallSiteFlags();
if (isFastScope(symbol)) {
- storeFastScopeVar(symbol, CALLSITE_SCOPE | getCallSiteFlags());
+ storeFastScopeVar(symbol, flags);
} else {
- method.dynamicSet(node.getName(), CALLSITE_SCOPE | getCallSiteFlags());
+ method.dynamicSet(node.getName(), flags, false);
}
} else {
- method.convert(node.getType());
- method.store(symbol);
+ final Type storeType = assignNode.getType();
+ if (symbol.hasSlotFor(storeType)) {
+ // Only emit a convert for a store known to be live; converts for dead stores can
+ // give us an unnecessary ClassCastException.
+ method.convert(storeType);
+ }
+ storeIdentWithCatchConversion(node, storeType);
}
return false;
@@ -3187,7 +4285,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
public boolean enterAccessNode(final AccessNode node) {
- method.dynamicSet(node.getProperty().getName(), getCallSiteFlags());
+ method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
return false;
}
@@ -3205,6 +4303,9 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
protected abstract void evaluate();
void store() {
+ if (target instanceof IdentNode) {
+ checkTemporalDeadZone((IdentNode)target);
+ }
prologue();
evaluate(); // leaves an operation of whatever the operationType was on the stack
storeNonDiscard();
@@ -3215,35 +4316,44 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
}
- private void newFunctionObject(final FunctionNode functionNode, final FunctionNode originalFunctionNode) {
+ private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
assert lc.peek() == functionNode;
- // We don't emit a ScriptFunction on stack for:
- // 1. the outermost compiled function (as there's no code being generated in its outer context that'd need it
- // as a callee), and
- // 2. for functions that are immediately called upon definition and they don't need a callee, e.g. (function(){})().
- // Such immediately-called functions are invoked using INVOKESTATIC (see enterFunctionNode() of the embedded
- // visitor of enterCallNode() for details), and if they don't need a callee, they don't have it on their
- // static method's parameter list.
- if (lc.getOutermostFunction() == functionNode ||
- (!functionNode.needsCallee()) && lc.isFunctionDefinedInCurrentCall(originalFunctionNode)) {
- return;
+
+ final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
+
+ if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
+ final CompileUnit fnUnit = functionNode.getCompileUnit();
+ final MethodEmitter createFunction = fnUnit.getClassEmitter().method(
+ EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
+ ScriptFunction.class, ScriptObject.class);
+ createFunction.begin();
+ createFunction._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
+ loadConstant(data, fnUnit, createFunction);
+ createFunction.load(SCOPE_TYPE, 0);
+ createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
+ createFunction._return();
+ createFunction.end();
}
- // Generate the object class and property map in case this function is ever used as constructor
- final String className = SCRIPTFUNCTION_IMPL_OBJECT;
- final int fieldCount = ObjectClassGenerator.getPaddedFieldCount(functionNode.countThisProperties());
- final String allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount));
- final PropertyMap allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
+ if (addInitializer && !compiler.isOnDemandCompilation()) {
+ compiler.addFunctionInitializer(data, functionNode);
+ }
- method._new(className).dup();
- loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), allocatorClassName, allocatorMap));
+ // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
+ // generated in its outer context that'd need it as a callee).
+ if (lc.getOutermostFunction() == functionNode) {
+ return;
+ }
+
+ method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
+ loadConstant(data);
- if (functionNode.isLazy() || functionNode.needsParentScope()) {
+ if (functionNode.needsParentScope()) {
method.loadCompilerConstant(SCOPE);
} else {
method.loadNull();
}
- method.invoke(constructorNoLookup(className, RecompilableScriptFunctionData.class, ScriptObject.class));
+ method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
}
// calls on Global class.
@@ -3251,10 +4361,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
}
- private MethodEmitter globalObjectPrototype() {
- return method.invokestatic(GLOBAL_OBJECT, "objectPrototype", methodDescriptor(ScriptObject.class));
- }
-
private MethodEmitter globalAllocateArguments() {
return method.invokestatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class));
}
@@ -3276,12 +4382,907 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
}
+ private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
+ return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
+ }
+
private MethodEmitter globalCheckObjectCoercible() {
return method.invokestatic(GLOBAL_OBJECT, "checkObjectCoercible", methodDescriptor(void.class, Object.class));
}
private MethodEmitter globalDirectEval() {
return method.invokestatic(GLOBAL_OBJECT, "directEval",
- methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class));
+ methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
+ }
+
+ private abstract class OptimisticOperation {
+ private final boolean isOptimistic;
+ // expression and optimistic are the same reference
+ private final Expression expression;
+ private final Optimistic optimistic;
+ private final TypeBounds resultBounds;
+
+ OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
+ this.optimistic = optimistic;
+ this.expression = (Expression)optimistic;
+ this.resultBounds = resultBounds;
+ this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
+ // Operation is only effectively optimistic if its type, after being coerced into the result bounds
+ // is narrower than the upper bound.
+ resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
+ }
+
+ MethodEmitter emit() {
+ return emit(0);
+ }
+
+ MethodEmitter emit(final int ignoredArgCount) {
+ final int programPoint = optimistic.getProgramPoint();
+ final boolean optimisticOrContinuation = isOptimistic || isContinuationEntryPoint(programPoint);
+ final boolean currentContinuationEntryPoint = isCurrentContinuationEntryPoint(programPoint);
+ final int stackSizeOnEntry = method.getStackSize() - ignoredArgCount;
+
+ // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
+ // allows us to not have to pop/load any arguments that are pushed onto it by loadStack() in the second
+ // storeStack().
+ storeStack(ignoredArgCount, optimisticOrContinuation);
+
+ // Now, load the stack
+ loadStack();
+
+ // Now store the values on the stack ultimately into local variables. In vast majority of cases, this is
+ // (aside from creating the local types map) a no-op, as the first opportunistic stack store will already
+ // store all variables. However, there can be operations in the loadStack() that invalidate some of the
+ // stack stores, e.g. in "x[i] = x[++i]", "++i" will invalidate the already stored value for "i". In such
+ // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
+ // stored into a local variable, although at the cost of doing a store/load on the loaded arguments as well.
+ final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
+ assert optimisticOrContinuation == (liveLocalsCount != -1);
+
+ final Label beginTry;
+ final Label catchLabel;
+ final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
+ if(isOptimistic) {
+ beginTry = new Label("try_optimistic");
+ final String catchLabelName = (afterConsumeStack == null ? "" : afterConsumeStack.toString()) + "_handler";
+ catchLabel = new Label(catchLabelName);
+ method.label(beginTry);
+ } else {
+ beginTry = catchLabel = null;
+ }
+
+ consumeStack();
+
+ if(isOptimistic) {
+ method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
+ }
+
+ if(isOptimistic || currentContinuationEntryPoint) {
+ method.label(afterConsumeStack);
+
+ final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
+ assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
+ final List<Type> localTypesList = method.getLocalVariableTypes();
+ final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
+ final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
+ assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;
+
+ if(isOptimistic) {
+ addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
+ }
+ if(currentContinuationEntryPoint) {
+ final ContinuationInfo ci = getContinuationInfo();
+ assert ci != null : "no continuation info found for " + lc.getCurrentFunction();
+ assert !ci.hasTargetLabel(); // No duplicate program points
+ ci.setTargetLabel(afterConsumeStack);
+ ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
+ // Can't rely on targetLabel.stack.localVariableTypes.length, as it can be higher due to effectively
+ // dead local variables.
+ ci.lvarCount = localTypes.size();
+ ci.setStackStoreSpec(localLoads);
+ ci.setStackTypes(Arrays.copyOf(method.getTypesFromStack(method.getStackSize()), stackSizeOnEntry));
+ assert ci.getStackStoreSpec().length == ci.getStackTypes().length;
+ ci.setReturnValueType(method.peekType());
+ ci.lineNumber = getLastLineNumber();
+ ci.catchLabel = catchLabels.peek();
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Stores the current contents of the stack into local variables so they are not lost before invoking something that
+ * can result in an {@code UnwarantedOptimizationException}.
+ * @param ignoreArgCount the number of topmost arguments on stack to ignore when deciding on the shape of the catch
+ * block. Those are used in the situations when we could not place the call to {@code storeStack} early enough
+ * (before emitting code for pushing the arguments that the optimistic call will pop). This is admittedly a
+ * deficiency in the design of the code generator when it deals with self-assignments and we should probably look
+ * into fixing it.
+ * @return types of the significant local variables after the stack was stored (types for local variables used
+ * for temporary storage of ignored arguments are not returned).
+ * @param optimisticOrContinuation if false, this method should not execute
+ * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
+ * currently live local variables, tailored to their types.
+ */
+ private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
+ if(!optimisticOrContinuation) {
+ return -1; // NOTE: correct value to return is lc.getUsedSlotCount(), but it wouldn't be used anyway
+ }
+
+ final int stackSize = method.getStackSize();
+ final Type[] stackTypes = method.getTypesFromStack(stackSize);
+ final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
+ final int usedSlots = method.getUsedSlotsWithLiveTemporaries();
+
+ final int firstIgnored = stackSize - ignoreArgCount;
+ // Find the first value on the stack (from the bottom) that is not a load from a local variable.
+ int firstNonLoad = 0;
+ while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
+ firstNonLoad++;
+ }
+
+ // Only do the store/load if first non-load is not an ignored argument. Otherwise, do nothing and return
+ // the number of used slots as the number of live local variables.
+ if(firstNonLoad >= firstIgnored) {
+ return usedSlots;
+ }
+
+ // Find the number of new temporary local variables that we need; it's the number of values on the stack that
+ // are not direct loads of existing local variables.
+ int tempSlotsNeeded = 0;
+ for(int i = firstNonLoad; i < stackSize; ++i) {
+ if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
+ tempSlotsNeeded += stackTypes[i].getSlots();
+ }
+ }
+
+ // Ensure all values on the stack that weren't directly loaded from a local variable are stored in a local
+ // variable. We're starting from highest local variable index, so that in case ignoreArgCount > 0 the ignored
+ // ones end up at the end of the local variable table.
+ int lastTempSlot = usedSlots + tempSlotsNeeded;
+ int ignoreSlotCount = 0;
+ for(int i = stackSize; i -- > firstNonLoad;) {
+ final int loadSlot = localLoadsOnStack[i];
+ if(loadSlot == Label.Stack.NON_LOAD) {
+ final Type type = stackTypes[i];
+ final int slots = type.getSlots();
+ lastTempSlot -= slots;
+ if(i >= firstIgnored) {
+ ignoreSlotCount += slots;
+ }
+ method.storeTemp(type, lastTempSlot);
+ } else {
+ method.pop();
+ }
+ }
+ assert lastTempSlot == usedSlots; // used all temporary locals
+
+ final List<Type> localTypesList = method.getLocalVariableTypes();
+
+ // Load values back on stack.
+ for(int i = firstNonLoad; i < stackSize; ++i) {
+ final int loadSlot = localLoadsOnStack[i];
+ final Type stackType = stackTypes[i];
+ final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
+ final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
+ final Type lvarType = localTypesList.get(lvarSlot);
+ method.load(lvarType, lvarSlot);
+ if(isLoad) {
+ // Conversion operators (I2L etc.) preserve "load"-ness of the value despite the fact that, in the
+ // strict sense they are creating a derived value from the loaded value. This special behavior of
+ // on-stack conversion operators is necessary to accommodate for differences in local variable types
+ // after deoptimization; having a conversion operator throw away "load"-ness would create different
+ // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
+ // After we load the value back, we need to redo the conversion to the stack type if stack type is
+ // different.
+ // NOTE: this would only strictly be necessary for widening conversions (I2L, L2D, I2D), and not for
+ // narrowing ones (L2I, D2L, D2I) as only widening conversions are the ones that can get eliminated
+ // in a deoptimized method, as their original input argument got widened. Maybe experiment with
+ // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
+ method.convert(stackType);
+ } else {
+ // temporary stores never needs a convert, as their type is always the same as the stack type.
+ assert lvarType == stackType;
+ lastTempSlot += lvarType.getSlots();
+ }
+ }
+ // used all temporaries
+ assert lastTempSlot == usedSlots + tempSlotsNeeded;
+
+ return lastTempSlot - ignoreSlotCount;
+ }
+
+ private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
+ final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
+ final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
+ Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
+ if(labels == null) {
+ labels = new LinkedList<>();
+ unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
+ }
+ method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
+ labels.add(label);
+ }
+
+ abstract void loadStack();
+
+ // Make sure that whatever indy call site you emit from this method uses {@code getCallSiteFlagsOptimistic(node)}
+ // or otherwise ensure optimistic flag is correctly set in the call site, otherwise it doesn't make much sense
+ // to use OptimisticExpression for emitting it.
+ abstract void consumeStack();
+
+ /**
+ * Emits the correct dynamic getter code. Normally just delegates to method emitter, except when the target
+ * expression is optimistic, and the desired type is narrower than the optimistic type. In that case, it'll emit a
+ * dynamic getter with its original optimistic type, and explicitly insert a narrowing conversion. This way we can
+ * preserve the optimism of the values even if they're subsequently immediately coerced into a narrower type. This
+ * is beneficial because in this case we can still presume that since the original getter was optimistic, the
+ * conversion has no side effects.
+ * @param name the name of the property being get
+ * @param flags call site flags
+ * @param isMethod whether we're preferrably retrieving a function
+ * @return the current method emitter
+ */
+ MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
+ if(isOptimistic) {
+ return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod, isIndex);
+ }
+ return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
+ }
+
+ MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
+ if(isOptimistic) {
+ return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
+ }
+ return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
+ }
+
+ MethodEmitter dynamicCall(final int argCount, final int flags) {
+ if (isOptimistic) {
+ return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
+ }
+ return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
+ }
+
+ int getOptimisticFlags(final int flags) {
+ return flags | CALLSITE_OPTIMISTIC | (optimistic.getProgramPoint() << CALLSITE_PROGRAM_POINT_SHIFT); //encode program point in high bits
+ }
+
+ int getProgramPoint() {
+ return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
+ }
+
+ void convertOptimisticReturnValue() {
+ if (isOptimistic) {
+ final Type optimisticType = getOptimisticCoercedType();
+ if(!optimisticType.isObject()) {
+ method.load(optimistic.getProgramPoint());
+ if(optimisticType.isInteger()) {
+ method.invoke(ENSURE_INT);
+ } else if(optimisticType.isLong()) {
+ method.invoke(ENSURE_LONG);
+ } else if(optimisticType.isNumber()) {
+ method.invoke(ENSURE_NUMBER);
+ } else {
+ throw new AssertionError(optimisticType);
+ }
+ }
+ }
+ }
+
+ void replaceCompileTimeProperty() {
+ final IdentNode identNode = (IdentNode)expression;
+ final String name = identNode.getSymbol().getName();
+ if (CompilerConstants.__FILE__.name().equals(name)) {
+ replaceCompileTimeProperty(getCurrentSource().getName());
+ } else if (CompilerConstants.__DIR__.name().equals(name)) {
+ replaceCompileTimeProperty(getCurrentSource().getBase());
+ } else if (CompilerConstants.__LINE__.name().equals(name)) {
+ replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
+ }
+ }
+
+ /**
+ * When an ident with name __FILE__, __DIR__, or __LINE__ is loaded, we'll try to look it up as any other
+ * identifier. However, if it gets all the way up to the Global object, it will send back a special value that
+ * represents a placeholder for these compile-time location properties. This method will generate code that loads
+ * the value of the compile-time location property and then invokes a method in Global that will replace the
+ * placeholder with the value. Effectively, if the symbol for these properties is defined anywhere in the lexical
+ * scope, they take precedence, but if they aren't, then they resolve to the compile-time location property.
+ * @param propertyValue the actual value of the property
+ */
+ private void replaceCompileTimeProperty(final Object propertyValue) {
+ assert method.peekType().isObject();
+ if(propertyValue instanceof String || propertyValue == null) {
+ method.load((String)propertyValue);
+ } else if(propertyValue instanceof Integer) {
+ method.load(((Integer)propertyValue).intValue());
+ method.convert(Type.OBJECT);
+ } else {
+ throw new AssertionError();
+ }
+ globalReplaceLocationPropertyPlaceholder();
+ convertOptimisticReturnValue();
+ }
+
+ /**
+ * Returns the type that should be used as the return type of the dynamic invocation that is emitted as the code
+ * for the current optimistic operation. If the type bounds is exact boolean or narrower than the expression's
+ * optimistic type, then the optimistic type is returned, otherwise the coercing type. Effectively, this method
+ * allows for moving the coercion into the optimistic type when it won't adversely affect the optimistic
+ * evaluation semantics, and for preserving the optimistic type and doing a separate coercion when it would
+ * affect it.
+ * @return
+ */
+ private Type getOptimisticCoercedType() {
+ final Type optimisticType = expression.getType();
+ assert resultBounds.widest.widerThan(optimisticType);
+ final Type narrowest = resultBounds.narrowest;
+
+ if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
+ assert !optimisticType.isObject();
+ return optimisticType;
+ }
+ assert !narrowest.isObject();
+ return narrowest;
+ }
+ }
+
+ private static boolean isOptimistic(final Optimistic optimistic) {
+ if(!optimistic.canBeOptimistic()) {
+ return false;
+ }
+ final Expression expr = (Expression)optimistic;
+ return expr.getType().narrowerThan(expr.getWidestOperationType());
+ }
+
+ private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
+ for (final int load : loads) {
+ if(load < 0 || load >= localCount) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean everyStackValueIsLocalLoad(final int[] loads) {
+ for (final int load : loads) {
+ if(load == Label.Stack.NON_LOAD) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
+ final int count = localVarTypes.size();
+ final StringBuilder desc = new StringBuilder(count);
+ for(int i = 0; i < count;) {
+ i += appendType(desc, localVarTypes.get(i));
+ }
+ return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
+ }
+
+ private static int appendType(final StringBuilder b, final Type t) {
+ b.append(t.getBytecodeStackType());
+ return t.getSlots();
+ }
+
+ private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
+ int count = 0;
+ for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
+ if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
+ ++count;
+ }
+ }
+ return count;
+
+ }
+ /**
+ * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
+ * strategy strives to maximize code reuse. Every handler constructs an array to hold the local variables, then
+ * fills in some trailing part of the local variables (those for which it has a unique suffix in the descriptor),
+ * then jumps to a handler for a prefix that's shared with other handlers. A handler that fills up locals up to
+ * position 0 will not jump to a prefix handler (as it has no prefix), but instead end with constructing and
+ * throwing a {@code RewriteException}. Since we lexicographically sort the entries, we only need to check every
+ * entry to its immediately preceding one for longest matching prefix.
+ * @return true if there is at least one exception handler
+ */
+ private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
+ if(!useOptimisticTypes()) {
+ return false;
+ }
+
+ // Take the mapping of lvarSpecs -> labels, and turn them into a descending lexicographically sorted list of
+ // handler specifications.
+ final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
+ if(unwarrantedOptimismHandlers.isEmpty()) {
+ return false;
+ }
+
+ method.lineNumber(0);
+
+ final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
+ for(final String spec: unwarrantedOptimismHandlers.keySet()) {
+ handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
+ }
+ Collections.sort(handlerSpecs, Collections.reverseOrder());
+
+ // Map of local variable specifications to labels for populating the array for that local variable spec.
+ final Map<String, Label> delegationLabels = new HashMap<>();
+
+ // Do everything in a single pass over the handlerSpecs list. Note that the list can actually grow as we're
+ // passing through it as we might add new prefix handlers into it, so can't hoist size() outside of the loop.
+ for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
+ final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
+ final String lvarSpec = spec.lvarSpec;
+ if(spec.catchTarget) {
+ assert !method.isReachable();
+ // Start a catch block and assign the labels for this lvarSpec with it.
+ method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
+ // This spec is a catch target, so emit array creation code. The length of the array is the number of
+ // symbols - the number of uppercase characters.
+ method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
+ method.newarray(Type.OBJECT_ARRAY);
+ }
+ if(spec.delegationTarget) {
+ // If another handler can delegate to this handler as its prefix, then put a jump target here for the
+ // shared code (after the array creation code, which is never shared).
+ method.label(delegationLabels.get(lvarSpec)); // label must exist
+ }
+
+ final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;
+
+ int lvarIndex;
+ final int firstArrayIndex;
+ final int firstLvarIndex;
+ Label delegationLabel;
+ final String commonLvarSpec;
+ if(lastHandler) {
+ // Last handler block, doesn't delegate to anything.
+ lvarIndex = 0;
+ firstLvarIndex = 0;
+ firstArrayIndex = 0;
+ delegationLabel = null;
+ commonLvarSpec = null;
+ } else {
+ // Not yet the last handler block, will definitely delegate to another handler; let's figure out which
+ // one. It can be an already declared handler further down the list, or it might need to declare a new
+ // prefix handler.
+
+ // Since we're lexicographically ordered, the common prefix handler is defined by the common prefix of
+ // this handler and the next handler on the list.
+ final int nextHandlerIndex = handlerIndex + 1;
+ final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
+ commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
+ // We don't chop symbols in half
+ assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));
+
+ // Let's find if we already have a declaration for such handler, or we need to insert it.
+ {
+ boolean addNewHandler = true;
+ int commonHandlerIndex = nextHandlerIndex;
+ for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
+ final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
+ final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
+ if(forwardLvarSpec.equals(commonLvarSpec)) {
+ // We already have a handler for the common prefix.
+ addNewHandler = false;
+ // Make sure we mark it as a delegation target.
+ forwardHandlerSpec.delegationTarget = true;
+ break;
+ } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
+ break;
+ }
+ }
+ if(addNewHandler) {
+ // We need to insert a common prefix handler. Note handlers created with catchTarget == false
+ // will automatically have delegationTarget == true (because that's the only reason for their
+ // existence).
+ handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
+ }
+ }
+
+ firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
+ lvarIndex = 0;
+ for(int j = 0; j < commonLvarSpec.length(); ++j) {
+ lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
+ }
+ firstLvarIndex = lvarIndex;
+
+ // Create a delegation label if not already present
+ delegationLabel = delegationLabels.get(commonLvarSpec);
+ if(delegationLabel == null) {
+ // uo_pa == "unwarranted optimism, populate array"
+ delegationLabel = new Label("uo_pa_" + commonLvarSpec);
+ delegationLabels.put(commonLvarSpec, delegationLabel);
+ }
+ }
+
+ // Load local variables handled by this handler on stack
+ int args = 0;
+ boolean symbolHadValue = false;
+ for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
+ final char typeDesc = lvarSpec.charAt(typeIndex);
+ final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
+ if (!lvarType.isUnknown()) {
+ method.load(lvarType, lvarIndex);
+ symbolHadValue = true;
+ args++;
+ } else if(typeDesc == 'U' && !symbolHadValue) {
+ // Symbol boundary with undefined last value. Check if all previous values for this symbol were also
+ // undefined; if so, emit one explicit Undefined. This serves to ensure that we're emiting exactly
+ // one value for every symbol that uses local slots. While we could in theory ignore symbols that
+ // are undefined (in other words, dead) at the point where this exception was thrown, unfortunately
+ // we can't do it in practice. The reason for this is that currently our liveness analysis is
+ // coarse (it can determine whether a symbol has not been read with a particular type anywhere in
+ // the function being compiled, but that's it), and a symbol being promoted to Object due to a
+ // deoptimization will suddenly show up as "live for Object type", and previously dead U->O
+ // conversions on loop entries will suddenly become alive in the deoptimized method which will then
+ // expect a value for that slot in its continuation handler. If we had precise liveness analysis, we
+ // could go back to excluding known dead symbols from the payload of the RewriteException.
+ if(method.peekType() == Type.UNDEFINED) {
+ method.dup();
+ } else {
+ method.loadUndefined(Type.OBJECT);
+ }
+ args++;
+ }
+ if(Character.isUpperCase(typeDesc)) {
+ // Reached symbol boundary; reset flag for the next symbol.
+ symbolHadValue = false;
+ }
+ lvarIndex += lvarType.getSlots();
+ }
+ assert args > 0;
+ // Delegate actual storing into array to an array populator utility method.
+ //on the stack:
+ // object array to be populated
+ // start index
+ // a lot of types
+ method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
+ if(delegationLabel != null) {
+ // We cascade to a prefix handler to fill out the rest of the local variables and throw the
+ // RewriteException.
+ assert !lastHandler;
+ assert commonLvarSpec != null;
+ // Must undefine the local variables that we have already processed for the sake of correct join on the
+ // delegate label
+ method.undefineLocalVariables(firstLvarIndex, true);
+ final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
+ // If the delegate immediately follows, and it's not a catch target (so it doesn't have array setup
+ // code) don't bother emitting a jump, as we'd just jump to the next instruction.
+ if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
+ method._goto(delegationLabel);
+ }
+ } else {
+ assert lastHandler;
+ // Nothing to delegate to, so this handler must create and throw the RewriteException.
+ // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
+ // stack. We need to create a RewriteException, push two references to it below the constructor
+ // arguments, invoke the constructor, and throw the exception.
+ loadConstant(getByteCodeSymbolNames(fn));
+ if (isRestOf()) {
+ loadConstant(getContinuationEntryPoints());
+ method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
+ } else {
+ method.invoke(CREATE_REWRITE_EXCEPTION);
+ }
+ method.athrow();
+ }
+ }
+ return true;
+ }
+
+ private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
+ // Only names of local variables on the function level are captured. This information is used to reduce
+ // deoptimizations, so as much as we can capture will help. We rely on the fact that function wide variables are
+ // all live all the time, so the array passed to rewrite exception contains one element for every slotted symbol
+ // here.
+ final List<String> names = new ArrayList<>();
+ for (final Symbol symbol: fn.getBody().getSymbols()) {
+ if (symbol.hasSlot()) {
+ if (symbol.isScope()) {
+ // slot + scope can only be true for parameters
+ assert symbol.isParam();
+ names.add(null);
+ } else {
+ names.add(symbol.getName());
+ }
+ }
+ }
+ return names.toArray(new String[names.size()]);
+ }
+
+ private static String commonPrefix(final String s1, final String s2) {
+ final int l1 = s1.length();
+ final int l = Math.min(l1, s2.length());
+ int lms = -1; // last matching symbol
+ for(int i = 0; i < l; ++i) {
+ final char c1 = s1.charAt(i);
+ if(c1 != s2.charAt(i)) {
+ return s1.substring(0, lms + 1);
+ } else if(Character.isUpperCase(c1)) {
+ lms = i;
+ }
+ }
+ return l == l1 ? s1 : s2;
+ }
+
+ private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
+ private final String lvarSpec;
+ private final boolean catchTarget;
+ private boolean delegationTarget;
+
+ OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
+ this.lvarSpec = lvarSpec;
+ this.catchTarget = catchTarget;
+ if(!catchTarget) {
+ delegationTarget = true;
+ }
+ }
+
+ @Override
+ public int compareTo(final OptimismExceptionHandlerSpec o) {
+ return lvarSpec.compareTo(o.lvarSpec);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
+ if(catchTarget) {
+ b.append(", catchTarget");
+ }
+ if(delegationTarget) {
+ b.append(", delegationTarget");
+ }
+ return b.append("]").toString();
+ }
+ }
+
+ private static class ContinuationInfo {
+ private final Label handlerLabel;
+ private Label targetLabel; // Label for the target instruction.
+ int lvarCount;
+ // Indices of local variables that need to be loaded on the stack when this node completes
+ private int[] stackStoreSpec;
+ // Types of values loaded on the stack
+ private Type[] stackTypes;
+ // If non-null, this node should perform the requisite type conversion
+ private Type returnValueType;
+ // If we are in the middle of an object literal initialization, we need to update the map
+ private PropertyMap objectLiteralMap;
+ // Object literal stack depth for object literal - not necessarly top if property is a tree
+ private int objectLiteralStackDepth = -1;
+ // The line number at the continuation point
+ private int lineNumber;
+ // The active catch label, in case the continuation point is in a try/catch block
+ private Label catchLabel;
+ // The number of scopes that need to be popped before control is transferred to the catch label.
+ private int exceptionScopePops;
+
+ ContinuationInfo() {
+ this.handlerLabel = new Label("continuation_handler");
+ }
+
+ Label getHandlerLabel() {
+ return handlerLabel;
+ }
+
+ boolean hasTargetLabel() {
+ return targetLabel != null;
+ }
+
+ Label getTargetLabel() {
+ return targetLabel;
+ }
+
+ void setTargetLabel(final Label targetLabel) {
+ this.targetLabel = targetLabel;
+ }
+
+ int[] getStackStoreSpec() {
+ return stackStoreSpec.clone();
+ }
+
+ void setStackStoreSpec(final int[] stackStoreSpec) {
+ this.stackStoreSpec = stackStoreSpec;
+ }
+
+ Type[] getStackTypes() {
+ return stackTypes.clone();
+ }
+
+ void setStackTypes(final Type[] stackTypes) {
+ this.stackTypes = stackTypes;
+ }
+
+ Type getReturnValueType() {
+ return returnValueType;
+ }
+
+ void setReturnValueType(final Type returnValueType) {
+ this.returnValueType = returnValueType;
+ }
+
+ int getObjectLiteralStackDepth() {
+ return objectLiteralStackDepth;
+ }
+
+ void setObjectLiteralStackDepth(final int objectLiteralStackDepth) {
+ this.objectLiteralStackDepth = objectLiteralStackDepth;
+ }
+
+ PropertyMap getObjectLiteralMap() {
+ return objectLiteralMap;
+ }
+
+ void setObjectLiteralMap(final PropertyMap objectLiteralMap) {
+ this.objectLiteralMap = objectLiteralMap;
+ }
+
+ @Override
+ public String toString() {
+ return "[localVariableTypes=" + targetLabel.getStack().getLocalVariableTypesCopy() + ", stackStoreSpec=" +
+ Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
+ }
+ }
+
+ private ContinuationInfo getContinuationInfo() {
+ return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
+ }
+
+ private void generateContinuationHandler() {
+ if (!isRestOf()) {
+ return;
+ }
+
+ final ContinuationInfo ci = getContinuationInfo();
+ method.label(ci.getHandlerLabel());
+
+ // There should never be an exception thrown from the continuation handler, but in case there is (meaning,
+ // Nashorn has a bug), then line number 0 will be an indication of where it came from (line numbers are Uint16).
+ method.lineNumber(0);
+
+ final Label.Stack stack = ci.getTargetLabel().getStack();
+ final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
+ final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
+ final int lvarCount = ci.lvarCount;
+
+ final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
+ // Store the RewriteException into an unused local variable slot.
+ method.load(rewriteExceptionType, 0);
+ method.storeTemp(rewriteExceptionType, lvarCount);
+ // Get local variable array
+ method.load(rewriteExceptionType, 0);
+ method.invoke(RewriteException.GET_BYTECODE_SLOTS);
+ // Store local variables. Note that deoptimization might introduce new value types for existing local variables,
+ // so we must use both liveLocals and symbolBoundary, as in some cases (when the continuation is inside of a try
+ // block) we need to store the incoming value into multiple slots. The optimism exception handlers will have
+ // exactly one array element for every symbol that uses bytecode storage. If in the originating method the value
+ // was undefined, there will be an explicit Undefined value in the array.
+ int arrayIndex = 0;
+ for(int lvarIndex = 0; lvarIndex < lvarCount;) {
+ final Type lvarType = lvarTypes.get(lvarIndex);
+ if(!lvarType.isUnknown()) {
+ method.dup();
+ method.load(arrayIndex).arrayload();
+ final Class<?> typeClass = lvarType.getTypeClass();
+ // Deoptimization in array initializers can cause arrays to undergo component type widening
+ if(typeClass == long[].class) {
+ method.load(rewriteExceptionType, lvarCount);
+ method.invoke(RewriteException.TO_LONG_ARRAY);
+ } else if(typeClass == double[].class) {
+ method.load(rewriteExceptionType, lvarCount);
+ method.invoke(RewriteException.TO_DOUBLE_ARRAY);
+ } else if(typeClass == Object[].class) {
+ method.load(rewriteExceptionType, lvarCount);
+ method.invoke(RewriteException.TO_OBJECT_ARRAY);
+ } else {
+ if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
+ // NOTE: this can only happen with dead stores. E.g. for the program "1; []; f();" in which the
+ // call to f() will deoptimize the call site, but it'll expect :return to have the type
+ // NativeArray. However, in the more optimal version, :return's only live type is int, therefore
+ // "{O}:return = []" is a dead store, and the variable will be sent into the continuation as
+ // Undefined, however NativeArray can't hold Undefined instance.
+ method.loadType(Type.getInternalName(typeClass));
+ method.invoke(RewriteException.INSTANCE_OR_NULL);
+ }
+ method.convert(lvarType);
+ }
+ method.storeHidden(lvarType, lvarIndex, false);
+ }
+ final int nextLvarIndex = lvarIndex + lvarType.getSlots();
+ if(symbolBoundary.get(nextLvarIndex - 1)) {
+ ++arrayIndex;
+ }
+ lvarIndex = nextLvarIndex;
+ }
+ if (AssertsEnabled.assertsEnabled()) {
+ method.load(arrayIndex);
+ method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
+ } else {
+ method.pop();
+ }
+
+ final int[] stackStoreSpec = ci.getStackStoreSpec();
+ final Type[] stackTypes = ci.getStackTypes();
+ final boolean isStackEmpty = stackStoreSpec.length == 0;
+ boolean replacedObjectLiteralMap = false;
+ if(!isStackEmpty) {
+ // Load arguments on the stack
+ final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth();
+ for(int i = 0; i < stackStoreSpec.length; ++i) {
+ final int slot = stackStoreSpec[i];
+ method.load(lvarTypes.get(slot), slot);
+ method.convert(stackTypes[i]);
+ // stack: s0=object literal being initialized
+ // change map of s0 so that the property we are initilizing when we failed
+ // is now ci.returnValueType
+ if (i == objectLiteralStackDepth) {
+ method.dup();
+ assert ci.getObjectLiteralMap() != null;
+ assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
+ loadConstant(ci.getObjectLiteralMap());
+ method.invoke(ScriptObject.SET_MAP);
+ replacedObjectLiteralMap = true;
+ }
+ }
+ }
+ // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth
+ assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap;
+ // Load RewriteException back.
+ method.load(rewriteExceptionType, lvarCount);
+ // Get rid of the stored reference
+ method.loadNull();
+ method.storeHidden(Type.OBJECT, lvarCount);
+ // Mark it dead
+ method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());
+
+ // Load return value on the stack
+ method.invoke(RewriteException.GET_RETURN_VALUE);
+
+ final Type returnValueType = ci.getReturnValueType();
+
+ // Set up an exception handler for primitive type conversion of return value if needed
+ boolean needsCatch = false;
+ final Label targetCatchLabel = ci.catchLabel;
+ Label _try = null;
+ if(returnValueType.isPrimitive()) {
+ // If the conversion throws an exception, we want to report the line number of the continuation point.
+ method.lineNumber(ci.lineNumber);
+
+ if(targetCatchLabel != METHOD_BOUNDARY) {
+ _try = new Label("");
+ method.label(_try);
+ needsCatch = true;
+ }
+ }
+
+ // Convert return value
+ method.convert(returnValueType);
+
+ final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;
+
+ // Declare a try/catch for the conversion. If no scopes need to be popped until the target catch block, just
+ // jump into it. Otherwise, we'll need to create a scope-popping catch block below.
+ final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
+ if(needsCatch) {
+ final Label _end_try = new Label("");
+ method.label(_end_try);
+ method._try(_try, _end_try, catchLabel);
+ }
+
+ // Jump to continuation point
+ method._goto(ci.getTargetLabel());
+
+ // Make a scope-popping exception delegate if needed
+ if(catchLabel != targetCatchLabel) {
+ method.lineNumber(0);
+ assert scopePopCount > 0;
+ method._catch(catchLabel);
+ popScopes(scopePopCount);
+ method.uncheckedGoto(targetCatchLabel);
+ }
}
}
diff --git a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index dcf1b1ba..87a0802c 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -31,7 +31,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
-
+import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
@@ -63,6 +63,10 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
* i.e. should we keep it or throw it away */
private final Deque<Node> discard = new ArrayDeque<>();
+ private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>();
+ private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>();
+ private final IntDeque splitNodes = new IntDeque();
+
/** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
* currently on the lexical context stack. */
private int[] nextFreeSlots = new int[16];
@@ -70,46 +74,56 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
/** size of next free slot vector */
private int nextFreeSlotsSize;
+ private boolean isWithBoundary(final LexicalContextNode node) {
+ return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
+ }
+
@Override
public <T extends LexicalContextNode> T push(final T node) {
- if (isDynamicScopeBoundary(node)) {
- ++dynamicScopeCount;
+ if (isWithBoundary(node)) {
+ dynamicScopeCount++;
+ } else if (node instanceof FunctionNode) {
+ if (((FunctionNode)node).inDynamicContext()) {
+ dynamicScopeCount++;
+ }
+ splitNodes.push(0);
}
return super.push(node);
}
+ void enterSplitNode() {
+ splitNodes.getAndIncrement();
+ pushFreeSlots(methodEmitters.peek().getUsedSlotsWithLiveTemporaries());
+ }
+
+ void exitSplitNode() {
+ final int count = splitNodes.decrementAndGet();
+ assert count >= 0;
+ }
+
@Override
public <T extends LexicalContextNode> T pop(final T node) {
final T popped = super.pop(node);
- if (isDynamicScopeBoundary(popped)) {
- --dynamicScopeCount;
- }
- if (node instanceof Block) {
- --nextFreeSlotsSize;
- }
- return popped;
- }
-
- private boolean isDynamicScopeBoundary(final LexicalContextNode node) {
- if (node instanceof Block) {
- // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
- // processing of WithNode.expression too, but it should be unaffected.
- return !isEmpty() && peek() instanceof WithNode;
+ if (isWithBoundary(node)) {
+ dynamicScopeCount--;
+ assert dynamicScopeCount >= 0;
} else if (node instanceof FunctionNode) {
- // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
- // variable into the function's scope), and it isn't strict (as evals in strict functions get an
- // isolated scope).
- return isFunctionDynamicScope((FunctionNode)node);
+ if (((FunctionNode)node).inDynamicContext()) {
+ dynamicScopeCount--;
+ assert dynamicScopeCount >= 0;
+ }
+ assert splitNodes.peek() == 0;
+ splitNodes.pop();
}
- return false;
+ return popped;
}
boolean inDynamicScope() {
return dynamicScopeCount > 0;
}
- static boolean isFunctionDynamicScope(FunctionNode fn) {
- return fn.hasEval() && !fn.isStrict();
+ boolean inSplitNode() {
+ return !splitNodes.isEmpty() && splitNodes.peek() > 0;
}
MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
@@ -123,6 +137,20 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
return methodEmitters.isEmpty() ? null : methodEmitters.peek();
}
+ void pushUnwarrantedOptimismHandlers() {
+ unwarrantedOptimismHandlers.push(new HashMap<String, Collection<Label>>());
+ slotTypesDescriptors.push(new StringBuilder());
+ }
+
+ Map<String, Collection<Label>> getUnwarrantedOptimismHandlers() {
+ return unwarrantedOptimismHandlers.peek();
+ }
+
+ Map<String, Collection<Label>> popUnwarrantedOptimismHandlers() {
+ slotTypesDescriptors.pop();
+ return unwarrantedOptimismHandlers.pop();
+ }
+
CompileUnit pushCompileUnit(final CompileUnit newUnit) {
compileUnits.push(newUnit);
return newUnit;
@@ -130,7 +158,9 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
CompileUnit popCompileUnit(final CompileUnit oldUnit) {
assert compileUnits.peek() == oldUnit;
- compileUnits.pop();
+ final CompileUnit unit = compileUnits.pop();
+ assert unit.hasCode() : "compile unit popped without code";
+ unit.setUsed();
return compileUnits.isEmpty() ? null : compileUnits.peek();
}
@@ -167,50 +197,77 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
* Get a shared static method representing a dynamic scope get access.
*
* @param unit current compile unit
- * @param type the type of the variable
* @param symbol the symbol
+ * @param valueType the type of the variable
* @param flags the callsite flags
* @return an object representing a shared scope call
*/
- SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) {
- final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
- if (scopeCalls.containsKey(scopeCall)) {
- return scopeCalls.get(scopeCall);
- }
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
- scopeCalls.put(scopeCall, scopeCall);
- return scopeCall;
+ SharedScopeCall getScopeGet(final CompileUnit unit, final Symbol symbol, final Type valueType, final int flags) {
+ return getScopeCall(unit, symbol, valueType, valueType, null, flags);
}
+ void onEnterBlock(final Block block) {
+ pushFreeSlots(assignSlots(block, isFunctionBody() ? 0 : getUsedSlotCount()));
+ }
- void nextFreeSlot(final Block block) {
- final boolean isFunctionBody = isFunctionBody();
-
- final int nextFreeSlot;
- if (isFunctionBody) {
- // On entry to function, start with slot 0
- nextFreeSlot = 0;
- } else {
- // Otherwise, continue from previous block's first free slot
- nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- }
+ private void pushFreeSlots(final int freeSlots) {
if (nextFreeSlotsSize == nextFreeSlots.length) {
final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
nextFreeSlots = newNextFreeSlots;
}
- nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
+ nextFreeSlots[nextFreeSlotsSize++] = freeSlots;
+ }
+
+ int getUsedSlotCount() {
+ return nextFreeSlots[nextFreeSlotsSize - 1];
+ }
+
+ void releaseSlots() {
+ --nextFreeSlotsSize;
+ final int undefinedFromSlot = nextFreeSlotsSize == 0 ? 0 : nextFreeSlots[nextFreeSlotsSize - 1];
+ if(!slotTypesDescriptors.isEmpty()) {
+ slotTypesDescriptors.peek().setLength(undefinedFromSlot);
+ }
+ methodEmitters.peek().undefineLocalVariables(undefinedFromSlot, false);
}
- private static int assignSlots(final Block block, final int firstSlot) {
- int nextSlot = firstSlot;
+ private int assignSlots(final Block block, final int firstSlot) {
+ int fromSlot = firstSlot;
+ final MethodEmitter method = methodEmitters.peek();
for (final Symbol symbol : block.getSymbols()) {
if (symbol.hasSlot()) {
- symbol.setSlot(nextSlot);
- nextSlot += symbol.slotCount();
+ symbol.setFirstSlot(fromSlot);
+ final int toSlot = fromSlot + symbol.slotCount();
+ method.defineBlockLocalVariable(fromSlot, toSlot);
+ fromSlot = toSlot;
}
}
- return nextSlot;
+ return fromSlot;
+ }
+
+ static Type getTypeForSlotDescriptor(final char typeDesc) {
+ // Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see
+ // MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor().
+ switch (typeDesc) {
+ case 'I':
+ case 'i':
+ return Type.INT;
+ case 'J':
+ case 'j':
+ return Type.LONG;
+ case 'D':
+ case 'd':
+ return Type.NUMBER;
+ case 'A':
+ case 'a':
+ return Type.OBJECT;
+ case 'U':
+ case 'u':
+ return Type.UNKNOWN;
+ default:
+ throw new AssertionError();
+ }
}
void pushDiscard(final Node node) {
@@ -225,11 +282,8 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
return discard.peek();
}
- int quickSlot(final Symbol symbol) {
- final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
- nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
- return quickSlot;
+ int quickSlot(final Type type) {
+ return methodEmitters.peek().defineTemporaryLocalVariable(type.getSlots());
}
-
}
diff --git a/src/jdk/nashorn/internal/codegen/CompilationPhase.java b/src/jdk/nashorn/internal/codegen/CompilationPhase.java
index 6c0a673d..2a1d2661 100644
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java
@@ -1,492 +1,694 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
package jdk.nashorn.internal.codegen;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.ATTR;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BUILTINS_TRANSFORMED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_GENERATED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_INSTALLED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.FINALIZED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.OPTIMISTIC_TYPES_ASSIGNED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.PARSED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SCOPE_DEPTHS_COMPUTED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
+import java.io.PrintWriter;
import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
-import jdk.nashorn.internal.codegen.types.Range;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.AssertsEnabled;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.CodeInstaller;
+import jdk.nashorn.internal.runtime.FunctionInitializer;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
-import jdk.nashorn.internal.runtime.Timing;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
/**
* A compilation phase is a step in the processes of turning a JavaScript
* FunctionNode into bytecode. It has an optional return value.
*/
enum CompilationPhase {
-
- /*
- * Lazy initialization - tag all function nodes not the script as lazy as
- * default policy. The will get trampolines and only be generated when
- * called
+ /**
+ * Constant folding pass Simple constant folding that will make elementary
+ * constructs go away
*/
- LAZY_INITIALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED)) {
+ CONSTANT_FOLDING_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-
- /*
- * For lazy compilation, we might be given a node previously marked
- * as lazy to compile as the outermost function node in the
- * compiler. Unmark it so it can be compiled and not cause
- * recursion. Make sure the return type is unknown so it can be
- * correctly deduced. Return types are always Objects in Lazy nodes
- * as we haven't got a change to generate code for them and decude
- * its parameter specialization
- *
- * TODO: in the future specializations from a callsite will be
- * passed here so we can generate a better non-lazy version of a
- * function from a trampoline
- */
-
- final FunctionNode outermostFunctionNode = fn;
-
- final Set<FunctionNode> neverLazy = new HashSet<>();
- final Set<FunctionNode> lazy = new HashSet<>();
-
- FunctionNode newFunctionNode = outermostFunctionNode;
-
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- // self references are done with invokestatic and thus cannot
- // have trampolines - never lazy
- @Override
- public boolean enterCallNode(final CallNode node) {
- final Node callee = node.getFunction();
- if (callee instanceof FunctionNode) {
- neverLazy.add(((FunctionNode)callee));
- return false;
- }
- return true;
- }
-
- //any function that isn't the outermost one must be marked as lazy
- @Override
- public boolean enterFunctionNode(final FunctionNode node) {
- assert compiler.isLazy();
- lazy.add(node);
- return true;
- }
- });
-
- //at least one method is non lazy - the outermost one
- neverLazy.add(newFunctionNode);
-
- for (final FunctionNode node : neverLazy) {
- Compiler.LOG.fine(
- "Marking ",
- node.getName(),
- " as non lazy, as it's a self reference");
- lazy.remove(node);
- }
-
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public Node leaveFunctionNode(final FunctionNode functionNode) {
- if (lazy.contains(functionNode)) {
- Compiler.LOG.fine(
- "Marking ",
- functionNode.getName(),
- " as lazy");
- final FunctionNode parent = lc.getParentFunction(functionNode);
- assert parent != null;
- lc.setFlag(parent, FunctionNode.HAS_LAZY_CHILDREN);
- lc.setBlockNeedsScope(parent.getBody());
- lc.setFlag(functionNode, FunctionNode.IS_LAZY);
- return functionNode;
- }
-
- return functionNode.
- clearFlag(lc, FunctionNode.IS_LAZY).
- setReturnType(lc, Type.UNKNOWN);
- }
- });
-
- return newFunctionNode;
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new FoldConstants(compiler));
}
@Override
public String toString() {
- return "[Lazy JIT Initialization]";
+ return "'Constant Folding'";
}
},
- /*
- * Constant folding pass Simple constant folding that will make elementary
- * constructs go away
+ /**
+ * Lower (Control flow pass) Finalizes the control flow. Clones blocks for
+ * finally constructs and similar things. Establishes termination criteria
+ * for nodes Guarantee return instructions to method making sure control
+ * flow cannot fall off the end. Replacing high level nodes with lower such
+ * as runtime nodes where applicable.
*/
- CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED, PARSED)) {
+ LOWERING_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- return (FunctionNode)fn.accept(new FoldConstants());
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new Lower(compiler));
}
@Override
public String toString() {
- return "[Constant Folding]";
+ return "'Control Flow Lowering'";
}
},
- /*
- * Lower (Control flow pass) Finalizes the control flow. Clones blocks for
- * finally constructs and similar things. Establishes termination criteria
- * for nodes Guarantee return instructions to method making sure control
- * flow cannot fall off the end. Replacing high level nodes with lower such
- * as runtime nodes where applicable.
+ /**
+ * Phase used only when doing optimistic code generation. It assigns all potentially
+ * optimistic ops a program point so that an UnwarrantedException knows from where
+ * a guess went wrong when creating the continuation to roll back this execution
*/
- LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
+ TRANSFORM_BUILTINS_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED)) {
+ //we only do this if we have a param type map, otherwise this is not a specialized recompile
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- return (FunctionNode)fn.accept(new Lower(compiler.getCodeInstaller()));
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return setStates(transformFunction(fn, new ApplySpecialization(compiler)), BUILTINS_TRANSFORMED);
}
@Override
public String toString() {
- return "[Control Flow Lowering]";
+ return "'Builtin Replacement'";
}
},
- /*
- * Attribution Assign symbols and types to all nodes.
+ /**
+ * Splitter Split the AST into several compile units based on a heuristic size calculation.
+ * Split IR can lead to scope information being changed.
*/
- ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) {
+ SPLITTING_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- final TemporarySymbols ts = compiler.getTemporarySymbols();
- final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
- if (compiler.getEnv()._print_mem_usage) {
- Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
- }
- return newFunctionNode;
- }
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ final CompileUnit outermostCompileUnit = compiler.addCompileUnit(0L);
+
+ FunctionNode newFunctionNode;
- /**
- * Pessimistically set all lazy functions' return types to Object
- * and the function symbols to object
- * @param functionNode node where to start iterating
- */
- private FunctionNode enterAttr(final FunctionNode functionNode, final TemporarySymbols ts) {
- return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ //ensure elementTypes, postsets and presets exist for splitter and arraynodes
+ newFunctionNode = transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
- public Node leaveFunctionNode(final FunctionNode node) {
- if (node.isLazy()) {
- FunctionNode newNode = node.setReturnType(lc, Type.OBJECT);
- return ts.ensureSymbol(lc, Type.OBJECT, newNode);
- }
- //node may have a reference here that needs to be nulled if it was referred to by
- //its outer context, if it is lazy and not attributed
- return node.setReturnType(lc, Type.UNKNOWN).setSymbol(lc, null);
+ public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
+ return literalNode.initialize(lc);
}
});
+
+ newFunctionNode = new Splitter(compiler, newFunctionNode, outermostCompileUnit).split(newFunctionNode, true);
+ newFunctionNode = transformFunction(newFunctionNode, new SplitIntoFunctions(compiler));
+ assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn=" + fn.getName() + ", fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
+ assert newFunctionNode.isStrict() == compiler.isStrict() : "functionNode.isStrict() != compiler.isStrict() for " + quote(newFunctionNode.getName());
+
+ return newFunctionNode;
}
@Override
public String toString() {
- return "[Type Attribution]";
+ return "'Code Splitting'";
}
},
- /*
- * Range analysis
- * Conservatively prove that certain variables can be narrower than
- * the most generic number type
- */
- RANGE_ANALYSIS_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
+ PROGRAM_POINT_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- if (!compiler.getEnv()._range_analysis) {
- return fn;
- }
-
- FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
- final List<ReturnNode> returns = new ArrayList<>();
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new ProgramPoints());
+ }
- newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>();
+ @Override
+ public String toString() {
+ return "'Program Point Calculation'";
+ }
+ },
+ SERIALIZE_SPLIT_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterFunctionNode(final FunctionNode functionNode) {
- returnStack.push(new ArrayList<ReturnNode>());
+ if (functionNode.isSplit()) {
+ compiler.serializeAst(functionNode);
+ }
return true;
}
+ });
+ }
- @Override
- public Node leaveFunctionNode(final FunctionNode functionNode) {
- Type returnType = Type.UNKNOWN;
- for (final ReturnNode ret : returnStack.pop()) {
- if (ret.getExpression() == null) {
- returnType = Type.OBJECT;
- break;
- }
- returnType = Type.widest(returnType, ret.getExpression().getType());
- }
- return functionNode.setReturnType(lc, returnType);
- }
+ @Override
+ public String toString() {
+ return "'Serialize Split Functions'";
+ }
+ },
- @Override
- public Node leaveReturnNode(final ReturnNode returnNode) {
- final ReturnNode result = (ReturnNode)leaveDefault(returnNode);
- returns.add(result);
- return result;
- }
+ SYMBOL_ASSIGNMENT_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new AssignSymbols(compiler));
+ }
- @Override
- public Node leaveDefault(final Node node) {
- if(node instanceof Expression) {
- final Expression expr = (Expression)node;
- final Symbol symbol = expr.getSymbol();
- if (symbol != null) {
- final Range range = symbol.getRange();
- final Type symbolType = symbol.getSymbolType();
- if (!symbolType.isNumeric()) {
- return expr;
- }
- final Type rangeType = range.getType();
- if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
- RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
- return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
- }
- }
- }
- return node;
- }
- });
+ @Override
+ public String toString() {
+ return "'Symbol Assignment'";
+ }
+ },
- Type returnType = Type.UNKNOWN;
- for (final ReturnNode node : returns) {
- if (node.getExpression() != null) {
- returnType = Type.widest(returnType, node.getExpression().getType());
- } else {
- returnType = Type.OBJECT;
- break;
- }
+ SCOPE_DEPTH_COMPUTATION_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ return transformFunction(fn, new FindScopeDepths(compiler));
+ }
+
+ @Override
+ public String toString() {
+ return "'Scope Depth Computation'";
+ }
+ },
+
+ OPTIMISTIC_TYPE_ASSIGNMENT_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ if (compiler.useOptimisticTypes()) {
+ return transformFunction(fn, new OptimisticTypesCalculator(compiler));
}
+ return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED);
+ }
- return newFunctionNode.setReturnType(null, returnType);
+ @Override
+ public String toString() {
+ return "'Optimistic Type Assignment'";
+ }
+ },
+
+ LOCAL_VARIABLE_TYPE_CALCULATION_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED,
+ OPTIMISTIC_TYPES_ASSIGNED)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ final FunctionNode newFunctionNode = transformFunction(fn, new LocalVariableTypesCalculator(compiler));
+ final ScriptEnvironment senv = compiler.getScriptEnvironment();
+ final PrintWriter err = senv.getErr();
+
+ //TODO separate phase for the debug printouts for abstraction and clarity
+ if (senv._print_lower_ast || fn.getFlag(FunctionNode.IS_PRINT_LOWER_AST)) {
+ err.println("Lower AST for: " + quote(newFunctionNode.getName()));
+ err.println(new ASTWriter(newFunctionNode));
+ }
+
+ if (senv._print_lower_parse || fn.getFlag(FunctionNode.IS_PRINT_LOWER_PARSE)) {
+ err.println("Lower AST for: " + quote(newFunctionNode.getName()));
+ err.println(new PrintVisitor(newFunctionNode));
+ }
+
+ return newFunctionNode;
}
@Override
public String toString() {
- return "[Range Analysis]";
+ return "'Local Variable Type Calculation'";
}
},
- /*
- * Splitter Split the AST into several compile units based on a size
- * heuristic Splitter needs attributed AST for weight calculations (e.g. is
- * a + b a ScriptRuntime.ADD with call overhead or a dadd with much less).
- * Split IR can lead to scope information being changed.
+ /**
+ * Reuse compile units, if they are already present. We are using the same compiler
+ * to recompile stuff
*/
- SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
+ REUSE_COMPILE_UNITS_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED,
+ OPTIMISTIC_TYPES_ASSIGNED,
+ LOCAL_VARIABLE_TYPES_CALCULATED)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ assert phases.isRestOfCompilation() : "reuse compile units currently only used for Rest-Of methods";
+
+ final Map<CompileUnit, CompileUnit> map = new HashMap<>();
+ final Set<CompileUnit> newUnits = CompileUnit.createCompileUnitSet();
- final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
+ final DebugLogger log = compiler.getLogger();
- assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
+ log.fine("Clearing bytecode cache");
+ compiler.clearBytecode();
- if (newFunctionNode.isStrict()) {
- assert compiler.getStrictMode();
- compiler.setStrictMode(true);
+ for (final CompileUnit oldUnit : compiler.getCompileUnits()) {
+ assert map.get(oldUnit) == null;
+ final CompileUnit newUnit = createNewCompileUnit(compiler, phases);
+ log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
+ map.put(oldUnit, newUnit);
+ assert newUnit != null;
+ newUnits.add(newUnit);
}
+ log.fine("Replacing compile units in Compiler...");
+ compiler.replaceCompileUnits(newUnits);
+ log.fine("Done");
+
+ //replace old compile units in function nodes, if any are assigned,
+ //for example by running the splitter on this function node in a previous
+ //partial code generation
+ final FunctionNode newFunctionNode = transformFunction(fn, new ReplaceCompileUnits() {
+ @Override
+ CompileUnit getReplacement(CompileUnit original) {
+ return map.get(original);
+ }
+
+ @Override
+ public Node leaveDefault(final Node node) {
+ return node.ensureUniqueLabels(lc);
+ }
+ });
+
return newFunctionNode;
}
@Override
public String toString() {
- return "[Code Splitting]";
+ return "'Reuse Compile Units'";
}
},
- /*
- * FinalizeTypes
- *
- * This pass finalizes the types for nodes. If Attr created wider types than
- * known during the first pass, convert nodes are inserted or access nodes
- * are specialized where scope accesses.
- *
- * Runtime nodes may be removed and primitivized or reintroduced depending
- * on information that was established in Attr.
- *
- * Contract: all variables must have slot assignments and scope assignments
- * before type finalization.
- */
- TYPE_FINALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT)) {
+ REINITIALIZE_SERIALIZED(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT)) {
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- final ScriptEnvironment env = compiler.getEnv();
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ final Set<CompileUnit> unitSet = CompileUnit.createCompileUnitSet();
+ final Map<CompileUnit, CompileUnit> unitMap = new HashMap<>();
- final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new FinalizeTypes(compiler.getTemporarySymbols()));
+ // Ensure that the FunctionNode's compile unit is the first in the list of new units. Install phase
+ // will use that as the root class.
+ createCompileUnit(fn.getCompileUnit(), unitSet, unitMap, compiler, phases);
- if (env._print_lower_ast) {
- env.getErr().println(new ASTWriter(newFunctionNode));
- }
+ final FunctionNode newFn = transformFunction(fn, new ReplaceCompileUnits() {
+ @Override
+ CompileUnit getReplacement(final CompileUnit oldUnit) {
+ final CompileUnit existing = unitMap.get(oldUnit);
+ if (existing != null) {
+ return existing;
+ }
+ return createCompileUnit(oldUnit, unitSet, unitMap, compiler, phases);
+ }
- if (env._print_lower_parse) {
- env.getErr().println(new PrintVisitor(newFunctionNode));
- }
+ @Override
+ public Node leaveFunctionNode(final FunctionNode fn2) {
+ return super.leaveFunctionNode(
+ // restore flags for deserialized nested function nodes
+ compiler.getScriptFunctionData(fn2.getId()).restoreFlags(lc, fn2));
+ };
+ });
+ compiler.replaceCompileUnits(unitSet);
+ return newFn;
+ }
- return newFunctionNode;
+ private CompileUnit createCompileUnit(final CompileUnit oldUnit, final Set<CompileUnit> unitSet,
+ final Map<CompileUnit, CompileUnit> unitMap, final Compiler compiler, final CompilationPhases phases) {
+ final CompileUnit newUnit = createNewCompileUnit(compiler, phases);
+ unitMap.put(oldUnit, newUnit);
+ unitSet.add(newUnit);
+ return newUnit;
}
@Override
public String toString() {
- return "[Type Finalization]";
+ return "'Deserialize'";
}
},
- /*
+ /**
* Bytecode generation:
*
* Generate the byte code class(es) resulting from the compiled FunctionNode
*/
- BYTECODE_GENERATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT, FINALIZED)) {
+ BYTECODE_GENERATION_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED,
+ OPTIMISTIC_TYPES_ASSIGNED,
+ LOCAL_VARIABLE_TYPES_CALCULATED)) {
+
@Override
- FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- final ScriptEnvironment env = compiler.getEnv();
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ final ScriptEnvironment senv = compiler.getScriptEnvironment();
+
FunctionNode newFunctionNode = fn;
+ //root class is special, as it is bootstrapped from createProgramFunction, thus it's skipped
+ //in CodeGeneration - the rest can be used as a working "is compile unit used" metric
+ fn.getCompileUnit().setUsed();
+
+ compiler.getLogger().fine("Starting bytecode generation for ", quote(fn.getName()), " - restOf=", phases.isRestOfCompilation());
+
+ final CodeGenerator codegen = new CodeGenerator(compiler, phases.isRestOfCompilation() ? compiler.getContinuationEntryPoints() : null);
+
try {
- final CodeGenerator codegen = new CodeGenerator(compiler);
- newFunctionNode = (FunctionNode)newFunctionNode.accept(codegen);
+ // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program
+ // in the lazy + optimistic world. See CodeGenerator.skipFunction().
+ newFunctionNode = transformFunction(newFunctionNode, codegen).setState(null, BYTECODE_GENERATED);
codegen.generateScopeCalls();
} catch (final VerifyError e) {
- if (env._verify_code || env._print_code) {
- env.getErr().println(e.getClass().getSimpleName() + ": " + e.getMessage());
- if (env._dump_on_error) {
- e.printStackTrace(env.getErr());
+ if (senv._verify_code || senv._print_code) {
+ senv.getErr().println(e.getClass().getSimpleName() + ": " + e.getMessage());
+ if (senv._dump_on_error) {
+ e.printStackTrace(senv.getErr());
}
} else {
throw e;
}
+ } catch (final Throwable e) {
+ // Provide source file and line number being compiled when the assertion occurred
+ throw new AssertionError("Failed generating bytecode for " + fn.getSourceName() + ":" + codegen.getLastLineNumber(), e);
}
for (final CompileUnit compileUnit : compiler.getCompileUnits()) {
final ClassEmitter classEmitter = compileUnit.getClassEmitter();
classEmitter.end();
+ if (!compileUnit.isUsed()) {
+ compiler.getLogger().fine("Skipping unused compile unit ", compileUnit);
+ continue;
+ }
+
final byte[] bytecode = classEmitter.toByteArray();
assert bytecode != null;
final String className = compileUnit.getUnitClassName();
+ compiler.addClass(className, bytecode); //classes are only added to the bytecode map if compile unit is used
- compiler.addClass(className, bytecode);
-
- // should could be printed to stderr for generate class?
- if (env._print_code) {
- final StringBuilder sb = new StringBuilder();
- sb.append("class: " + className).append('\n')
- .append(ClassEmitter.disassemble(bytecode))
- .append("=====");
- env.getErr().println(sb);
- }
+ CompileUnit.increaseEmitCount();
// should we verify the generated code?
- if (env._verify_code) {
+ if (senv._verify_code) {
compiler.getCodeInstaller().verify(bytecode);
}
- // should code be dumped to disk - only valid in compile_only mode?
- if (env._dest_dir != null && env._compile_only) {
- final String fileName = className.replace('.', File.separatorChar) + ".class";
- final int index = fileName.lastIndexOf(File.separatorChar);
+ DumpBytecode.dumpBytecode(senv, compiler.getLogger(), bytecode, className);
+ }
- final File dir;
- if (index != -1) {
- dir = new File(env._dest_dir, fileName.substring(0, index));
- } else {
- dir = new File(env._dest_dir);
- }
+ return newFunctionNode;
+ }
- try {
- if (!dir.exists() && !dir.mkdirs()) {
- throw new IOException(dir.toString());
- }
- final File file = new File(env._dest_dir, fileName);
- try (final FileOutputStream fos = new FileOutputStream(file)) {
- fos.write(bytecode);
- }
- Compiler.LOG.info("Wrote class to '" + file.getAbsolutePath() + '\'');
- } catch (final IOException e) {
- Compiler.LOG.warning("Skipping class dump for ",
- className,
- ": ",
- ECMAErrors.getMessage(
- "io.error.cant.write",
- dir.toString()));
+ @Override
+ public String toString() {
+ return "'Bytecode Generation'";
+ }
+ },
+
+ INSTALL_PHASE(
+ EnumSet.of(
+ INITIALIZED,
+ PARSED,
+ CONSTANT_FOLDED,
+ LOWERED,
+ BUILTINS_TRANSFORMED,
+ SPLIT,
+ SYMBOLS_ASSIGNED,
+ SCOPE_DEPTHS_COMPUTED,
+ OPTIMISTIC_TYPES_ASSIGNED,
+ LOCAL_VARIABLE_TYPES_CALCULATED,
+ BYTECODE_GENERATED)) {
+
+ @Override
+ FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+ final DebugLogger log = compiler.getLogger();
+
+ final Map<String, Class<?>> installedClasses = new LinkedHashMap<>();
+
+ boolean first = true;
+ Class<?> rootClass = null;
+ long length = 0L;
+
+ final CodeInstaller<ScriptEnvironment> codeInstaller = compiler.getCodeInstaller();
+ final Map<String, byte[]> bytecode = compiler.getBytecode();
+
+ for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
+ final String className = entry.getKey();
+ //assert !first || className.equals(compiler.getFirstCompileUnit().getUnitClassName()) : "first=" + first + " className=" + className + " != " + compiler.getFirstCompileUnit().getUnitClassName();
+ final byte[] code = entry.getValue();
+ length += code.length;
+
+ final Class<?> clazz = codeInstaller.install(className, code);
+ if (first) {
+ rootClass = clazz;
+ first = false;
+ }
+ installedClasses.put(className, clazz);
+ }
+
+ if (rootClass == null) {
+ throw new CompilationException("Internal compiler error: root class not found!");
+ }
+
+ final Object[] constants = compiler.getConstantData().toArray();
+ codeInstaller.initialize(installedClasses.values(), compiler.getSource(), constants);
+
+ // initialize transient fields on recompilable script function data
+ for (final Object constant: constants) {
+ if (constant instanceof RecompilableScriptFunctionData) {
+ ((RecompilableScriptFunctionData)constant).initTransients(compiler.getSource(), codeInstaller);
+ }
+ }
+
+ // initialize function in the compile units
+ for (final CompileUnit unit : compiler.getCompileUnits()) {
+ if (!unit.isUsed()) {
+ continue;
+ }
+ unit.setCode(installedClasses.get(unit.getUnitClassName()));
+ }
+
+ if (!compiler.isOnDemandCompilation()) {
+ // Initialize functions
+ final Map<Integer, FunctionInitializer> initializers = compiler.getFunctionInitializers();
+ if (initializers != null) {
+ for (final Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
+ final FunctionInitializer initializer = entry.getValue();
+ initializer.setCode(installedClasses.get(initializer.getClassName()));
+ compiler.getScriptFunctionData(entry.getKey()).initializeCode(initializer);
}
}
}
- return newFunctionNode;
+ if (log.isEnabled()) {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append("Installed class '").
+ append(rootClass.getSimpleName()).
+ append('\'').
+ append(" [").
+ append(rootClass.getName()).
+ append(", size=").
+ append(length).
+ append(" bytes, ").
+ append(compiler.getCompileUnits().size()).
+ append(" compile unit(s)]");
+
+ log.fine(sb.toString());
+ }
+
+ return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
}
@Override
public String toString() {
- return "[Bytecode Generation]";
+ return "'Class Installation'";
}
- };
+ };
+
+ /** pre conditions required for function node to which this transform is to be applied */
private final EnumSet<CompilationState> pre;
+
+ /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
private long startTime;
+
+ /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
private long endTime;
+
+ /** boolean that is true upon transform completion */
private boolean isFinished;
private CompilationPhase(final EnumSet<CompilationState> pre) {
this.pre = pre;
}
- boolean isApplicable(final FunctionNode functionNode) {
- return functionNode.hasState(pre);
- }
-
- protected FunctionNode begin(final FunctionNode functionNode) {
- if (pre != null) {
- // check that everything in pre is present
- for (final CompilationState state : pre) {
- assert functionNode.hasState(state);
- }
- // check that nothing else is present
- for (final CompilationState state : CompilationState.values()) {
- assert !(functionNode.hasState(state) && !pre.contains(state));
- }
+ private static FunctionNode setStates(final FunctionNode functionNode, final CompilationState state) {
+ if (!AssertsEnabled.assertsEnabled()) {
+ return functionNode;
}
-
- startTime = System.currentTimeMillis();
- return functionNode;
+ return transformFunction(functionNode, new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public Node leaveFunctionNode(final FunctionNode fn) {
+ return fn.setState(lc, state);
+ }
+ });
}
- protected FunctionNode end(final FunctionNode functionNode) {
- endTime = System.currentTimeMillis();
- Timing.accumulateTime(toString(), endTime - startTime);
+ /**
+ * Start a compilation phase
+ * @param compiler the compiler to use
+ * @param functionNode function to compile
+ * @return function node
+ */
+ protected FunctionNode begin(final Compiler compiler, final FunctionNode functionNode) {
+ compiler.getLogger().indent();
+
+ assert pre != null;
+
+ if (!functionNode.hasState(pre)) {
+ final StringBuilder sb = new StringBuilder("Compilation phase ");
+ sb.append(this).
+ append(" is not applicable to ").
+ append(quote(functionNode.getName())).
+ append("\n\tFunctionNode state = ").
+ append(functionNode.getState()).
+ append("\n\tRequired state = ").
+ append(this.pre);
+
+ throw new CompilationException(sb.toString());
+ }
+
+ startTime = System.nanoTime();
+
+ return functionNode;
+ }
+
+ /**
+ * End a compilation phase
+ * @param compiler the compiler
+ * @param functionNode function node to compile
+ * @return function node
+ */
+ protected FunctionNode end(final Compiler compiler, final FunctionNode functionNode) {
+ compiler.getLogger().unindent();
+ endTime = System.nanoTime();
+ compiler.getScriptEnvironment()._timing.accumulateTime(toString(), endTime - startTime);
isFinished = true;
return functionNode;
@@ -504,13 +706,39 @@ enum CompilationPhase {
return endTime;
}
- abstract FunctionNode transform(final Compiler compiler, final FunctionNode functionNode) throws CompilationException;
+ abstract FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException;
- final FunctionNode apply(final Compiler compiler, final FunctionNode functionNode) throws CompilationException {
- if (!isApplicable(functionNode)) {
- throw new CompilationException("compile phase not applicable: " + this + " to " + functionNode.getName() + " state=" + functionNode.getState());
- }
- return end(transform(compiler, begin(functionNode)));
+ /**
+ * Apply a transform to a function node, returning the transfored function node. If the transform is not
+ * applicable, an exception is thrown. Every transform requires the function to have a certain number of
+ * states to operate. It can have more states set, but not fewer. The state list, i.e. the constructor
+ * arguments to any of the CompilationPhase enum entries, is a set of REQUIRED states.
+ *
+ * @param compiler compiler
+ * @param phases current complete pipeline of which this phase is one
+ * @param functionNode function node to transform
+ *
+ * @return transformed function node
+ *
+ * @throws CompilationException if function node lacks the state required to run the transform on it
+ */
+ final FunctionNode apply(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException {
+ assert phases.contains(this);
+
+ return end(compiler, transform(compiler, phases, begin(compiler, functionNode)));
+ }
+
+ private static FunctionNode transformFunction(final FunctionNode fn, final NodeVisitor<?> visitor) {
+ return (FunctionNode) fn.accept(visitor);
}
+ private static CompileUnit createNewCompileUnit(final Compiler compiler, final CompilationPhases phases) {
+ final StringBuilder sb = new StringBuilder(compiler.nextCompileUnitName());
+ if (phases.isRestOfCompilation()) {
+ sb.append("$restOf");
+ }
+ //it's ok to not copy the initCount, methodCount and clinitCount here, as codegen is what
+ //fills those out anyway. Thus no need for a copy constructor
+ return compiler.createCompileUnit(sb.toString(), 0);
+ }
}
diff --git a/src/jdk/nashorn/internal/codegen/CompileUnit.java b/src/jdk/nashorn/internal/codegen/CompileUnit.java
index 73127259..13e9d716 100644
--- a/src/jdk/nashorn/internal/codegen/CompileUnit.java
+++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java
@@ -25,28 +25,77 @@
package jdk.nashorn.internal.codegen;
+import java.io.Serializable;
+import java.util.Set;
+import java.util.TreeSet;
+import jdk.nashorn.internal.ir.CompileUnitHolder;
+
/**
- * Used to track split class compilation.
- */
-public class CompileUnit implements Comparable<CompileUnit> {
+ * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
+ * transient, making the serialized version of the class only useful for tracking the referential topology of other
+ * AST nodes referencing the same or different compile units. We do want to preserve this topology though as
+ * {@link CompileUnitHolder}s in a deserialized AST will undergo reinitialization.
+ */
+public final class CompileUnit implements Comparable<CompileUnit>, Serializable {
+ private static final long serialVersionUID = 1L;
+
/** Current class name */
- private final String className;
+ private transient final String className;
/** Current class generator */
- private ClassEmitter classEmitter;
+ private transient ClassEmitter classEmitter;
- private long weight;
+ private transient long weight;
- private Class<?> clazz;
+ private transient Class<?> clazz;
- CompileUnit(final String className, final ClassEmitter classEmitter) {
- this(className, classEmitter, 0L);
- }
+ private transient boolean isUsed;
+
+ private static int emittedUnitCount;
CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
this.className = className;
- this.classEmitter = classEmitter;
this.weight = initialWeight;
+ this.classEmitter = classEmitter;
+ }
+
+ static Set<CompileUnit> createCompileUnitSet() {
+ return new TreeSet<>();
+ }
+
+ static void increaseEmitCount() {
+ emittedUnitCount++;
+ }
+
+ /**
+ * Get the amount of emitted compile units so far in the system
+ * @return emitted compile unit count
+ */
+ public static int getEmittedUnitCount() {
+ return emittedUnitCount;
+ }
+
+ /**
+ * Check if this compile unit is used
+ * @return true if tagged as in use - i.e active code that needs to be generated
+ */
+ public boolean isUsed() {
+ return isUsed;
+ }
+
+ /**
+ * Check if a compile unit has code, not counting inits and clinits
+ * @return true of if there is "real code" in the compile unit
+ */
+ public boolean hasCode() {
+ return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
+ }
+
+ /**
+ * Tag this compile unit as used
+ */
+ public void setUsed() {
+ this.isUsed = true;
}
/**
@@ -80,14 +129,6 @@ public class CompileUnit implements Comparable<CompileUnit> {
}
/**
- * Get the current weight of the compile unit.
- * @return the unit's weight
- */
- long getWeight() {
- return weight;
- }
-
- /**
* Check if this compile unit can hold {@code weight} more units of weight
* @param w weight to check if can be added
* @return true if weight fits in this compile unit
@@ -112,13 +153,18 @@ public class CompileUnit implements Comparable<CompileUnit> {
return className;
}
+ private static String shortName(final String name) {
+ return name == null ? null : name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
+ }
+
@Override
public String toString() {
- return "[classname=" + className + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
+ final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>";
+ return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']';
}
@Override
- public int compareTo(CompileUnit o) {
+ public int compareTo(final CompileUnit o) {
return className.compareTo(o.className);
}
}
diff --git a/src/jdk/nashorn/internal/codegen/Compiler.java b/src/jdk/nashorn/internal/codegen/Compiler.java
index e4af587b..740022b2 100644
--- a/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -27,47 +27,48 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.DEFAULT_SCRIPT_NAME;
-import static jdk.nashorn.internal.codegen.CompilerConstants.LAZY;
import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
import java.io.File;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
-import java.util.EnumSet;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
-import java.util.TreeSet;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
import java.util.logging.Level;
import jdk.internal.dynalink.support.NameCodec;
-import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.TemporarySymbols;
+import jdk.nashorn.internal.ir.Optimistic;
import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import jdk.nashorn.internal.runtime.CodeInstaller;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ErrorManager;
+import jdk.nashorn.internal.runtime.FunctionInitializer;
+import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
-import jdk.nashorn.internal.runtime.Timing;
-import jdk.nashorn.internal.runtime.options.Options;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Responsible for converting JavaScripts to java byte code. Main entry
@@ -75,7 +76,8 @@ import jdk.nashorn.internal.runtime.options.Options;
* predefined Code installation policy, given to it at construction time.
* @see CodeInstaller
*/
-public final class Compiler {
+@Logger(name="compiler")
+public final class Compiler implements Loggable {
/** Name of the scripts package */
public static final String SCRIPTS_PACKAGE = "jdk/nashorn/internal/scripts";
@@ -83,9 +85,15 @@ public final class Compiler {
/** Name of the objects package */
public static final String OBJECTS_PACKAGE = "jdk/nashorn/internal/objects";
- private Source source;
+ private final ScriptEnvironment env;
+
+ private final Source source;
+
+ private final String sourceName;
- private String sourceName;
+ private final ErrorManager errors;
+
+ private final boolean optimistic;
private final Map<String, byte[]> bytecode;
@@ -93,403 +101,584 @@ public final class Compiler {
private final ConstantData constantData;
- private final CompilationSequence sequence;
+ private final CodeInstaller<ScriptEnvironment> installer;
- private final ScriptEnvironment env;
+ /** logger for compiler, trampolines, splits and related code generation events
+ * that affect classes */
+ private final DebugLogger log;
- private String scriptName;
+ private final Context context;
- private boolean strict;
+ private final TypeMap types;
- private final CodeInstaller<ScriptEnvironment> installer;
+ // Runtime scope in effect at the time of the compilation. Used to evaluate types of expressions and prevent overly
+ // optimistic assumptions (which will lead to unnecessary deoptimizing recompilations).
+ private final TypeEvaluator typeEvaluator;
- private final TemporarySymbols temporarySymbols = new TemporarySymbols();
+ private final boolean strict;
- /** logger for compiler, trampolines, splits and related code generation events
- * that affect classes */
- public static final DebugLogger LOG = new DebugLogger("compiler");
+ private final boolean onDemand;
/**
- * This array contains names that need to be reserved at the start
- * of a compile, to avoid conflict with variable names later introduced.
- * See {@link CompilerConstants} for special names used for structures
- * during a compile.
+ * If this is a recompilation, this is how we pass in the invalidations, e.g. programPoint=17, Type == int means
+ * that using whatever was at program point 17 as an int failed.
*/
- private static String[] RESERVED_NAMES = {
- SCOPE.symbolName(),
- THIS.symbolName(),
- RETURN.symbolName(),
- CALLEE.symbolName(),
- VARARGS.symbolName(),
- ARGUMENTS.symbolName()
- };
+ private final Map<Integer, Type> invalidatedProgramPoints;
+
+ /**
+ * Descriptor of the location where we write the type information after compilation.
+ */
+ private final Object typeInformationFile;
+
+ /**
+ * Compile unit name of first compile unit - this prefix will be used for all
+ * classes that a compilation generates.
+ */
+ private final String firstCompileUnitName;
+
+ /**
+ * Contains the program point that should be used as the continuation entry point, as well as all previous
+ * continuation entry points executed as part of a single logical invocation of the function. In practical terms, if
+ * we execute a rest-of method from the program point 17, but then we hit deoptimization again during it at program
+ * point 42, and execute a rest-of method from the program point 42, and then we hit deoptimization again at program
+ * point 57 and are compiling a rest-of method for it, the values in the array will be [57, 42, 17]. This is only
+ * set when compiling a rest-of method. If this method is a rest-of for a non-rest-of method, the array will have
+ * one element. If it is a rest-of for a rest-of, the array will have two elements, and so on.
+ */
+ private final int[] continuationEntryPoints;
+
+ /**
+ * ScriptFunction data for what is being compile, where applicable.
+ * TODO: make this immutable, propagate it through the CompilationPhases
+ */
+ private RecompilableScriptFunctionData compiledFunction;
/**
- * This class makes it possible to do your own compilation sequence
- * from the code generation package. There are predefined compilation
- * sequences already
+ * Most compile unit names are longer than the default StringBuilder buffer,
+ * worth startup performance when massive class generation is going on to increase
+ * this
*/
- @SuppressWarnings("serial")
- static class CompilationSequence extends LinkedList<CompilationPhase> {
+ private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
- CompilationSequence(final CompilationPhase... phases) {
- super(Arrays.asList(phases));
+ private final Map<Integer, byte[]> serializedAsts = new HashMap<>();
+
+ /**
+ * Compilation phases that a compilation goes through
+ */
+ public static class CompilationPhases implements Iterable<CompilationPhase> {
+
+ /**
+ * Singleton that describes compilation up to the phase where a function can be serialized.
+ */
+ private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases(
+ "Common initial phases",
+ CompilationPhase.CONSTANT_FOLDING_PHASE,
+ CompilationPhase.LOWERING_PHASE,
+ CompilationPhase.TRANSFORM_BUILTINS_PHASE,
+ CompilationPhase.SPLITTING_PHASE,
+ CompilationPhase.PROGRAM_POINT_PHASE,
+ CompilationPhase.SERIALIZE_SPLIT_PHASE
+ );
+
+ private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases(
+ "After common phases, before bytecode generator",
+ CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
+ CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+ CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
+ CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE
+ );
+
+ /**
+ * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not
+ * including) generating and installing code.
+ */
+ public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases(
+ "Recompile serialized function up to bytecode",
+ CompilationPhase.REINITIALIZE_SERIALIZED,
+ COMPILE_SERIALIZABLE_UPTO_BYTECODE
+ );
+
+ /**
+ * Singleton that describes back end of method generation, given that we have generated the normal
+ * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
+ */
+ public final static CompilationPhases GENERATE_BYTECODE_AND_INSTALL = new CompilationPhases(
+ "Generate bytecode and install",
+ CompilationPhase.BYTECODE_GENERATION_PHASE,
+ CompilationPhase.INSTALL_PHASE
+ );
+
+ /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
+ public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases(
+ "Compile upto bytecode",
+ COMPILE_UPTO_SERIALIZABLE,
+ COMPILE_SERIALIZABLE_UPTO_BYTECODE);
+
+ /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
+ public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases(
+ "Compile without install",
+ COMPILE_UPTO_BYTECODE,
+ CompilationPhase.BYTECODE_GENERATION_PHASE);
+
+ /** Singleton that describes a standard eager compilation - this includes code installation */
+ public final static CompilationPhases COMPILE_ALL = new CompilationPhases(
+ "Full eager compilation",
+ COMPILE_UPTO_BYTECODE,
+ GENERATE_BYTECODE_AND_INSTALL);
+
+ /** Singleton that describes a full compilation - this includes code installation - from serialized state*/
+ public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases(
+ "Eager compilation from serializaed state",
+ RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+ GENERATE_BYTECODE_AND_INSTALL);
+
+ /**
+ * Singleton that describes restOf method generation, given that we have generated the normal
+ * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
+ */
+ public final static CompilationPhases GENERATE_BYTECODE_AND_INSTALL_RESTOF = new CompilationPhases(
+ "Generate bytecode and install - RestOf method",
+ CompilationPhase.REUSE_COMPILE_UNITS_PHASE,
+ GENERATE_BYTECODE_AND_INSTALL);
+
+ /** Compile all for a rest of method */
+ public final static CompilationPhases COMPILE_ALL_RESTOF = new CompilationPhases(
+ "Compile all, rest of",
+ COMPILE_UPTO_BYTECODE,
+ GENERATE_BYTECODE_AND_INSTALL_RESTOF);
+
+ /** Compile from serialized for a rest of method */
+ public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases(
+ "Compile serialized, rest of",
+ RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+ GENERATE_BYTECODE_AND_INSTALL_RESTOF);
+
+ private final List<CompilationPhase> phases;
+
+ private final String desc;
+
+ private CompilationPhases(final String desc, final CompilationPhase... phases) {
+ this(desc, Arrays.asList(phases));
}
- CompilationSequence(final CompilationSequence sequence) {
- this(sequence.toArray(new CompilationPhase[sequence.size()]));
+ private CompilationPhases(final String desc, final CompilationPhases base, final CompilationPhase... phases) {
+ this(desc, concat(base.phases, Arrays.asList(phases)));
}
- CompilationSequence insertAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
- final CompilationSequence newSeq = new CompilationSequence();
- for (final CompilationPhase elem : this) {
- newSeq.add(phase);
- if (elem.equals(phase)) {
- newSeq.add(newPhase);
- }
- }
- assert newSeq.contains(newPhase);
- return newSeq;
+ private CompilationPhases(final String desc, final CompilationPhase first, final CompilationPhases rest) {
+ this(desc, concat(Collections.singletonList(first), rest.phases));
}
- CompilationSequence insertBefore(final CompilationPhase phase, final CompilationPhase newPhase) {
- final CompilationSequence newSeq = new CompilationSequence();
- for (final CompilationPhase elem : this) {
- if (elem.equals(phase)) {
- newSeq.add(newPhase);
- }
- newSeq.add(phase);
+ private CompilationPhases(final String desc, final CompilationPhases base) {
+ this(desc, base.phases);
+ }
+
+ private CompilationPhases(final String desc, final CompilationPhases... bases) {
+ this(desc, concatPhases(bases));
+ }
+
+ private CompilationPhases(final String desc, final List<CompilationPhase> phases) {
+ this.desc = desc;
+ this.phases = phases;
+ }
+
+ private static List<CompilationPhase> concatPhases(final CompilationPhases[] bases) {
+ final ArrayList<CompilationPhase> l = new ArrayList<>();
+ for(final CompilationPhases base: bases) {
+ l.addAll(base.phases);
}
- assert newSeq.contains(newPhase);
- return newSeq;
+ l.trimToSize();
+ return l;
}
- CompilationSequence insertFirst(final CompilationPhase phase) {
- final CompilationSequence newSeq = new CompilationSequence(this);
- newSeq.addFirst(phase);
- return newSeq;
+ private static <T> List<T> concat(final List<T> l1, final List<T> l2) {
+ final ArrayList<T> l = new ArrayList<>(l1);
+ l.addAll(l2);
+ l.trimToSize();
+ return l;
}
- CompilationSequence insertLast(final CompilationPhase phase) {
- final CompilationSequence newSeq = new CompilationSequence(this);
- newSeq.addLast(phase);
- return newSeq;
+ @Override
+ public String toString() {
+ return "'" + desc + "' " + phases.toString();
}
- }
- /**
- * Environment information known to the compile, e.g. params
- */
- public static class Hints {
- private final Type[] paramTypes;
+ boolean contains(final CompilationPhase phase) {
+ return phases.contains(phase);
+ }
- /** singleton empty hints */
- public static final Hints EMPTY = new Hints();
+ @Override
+ public Iterator<CompilationPhase> iterator() {
+ return phases.iterator();
+ }
- private Hints() {
- this.paramTypes = null;
+ boolean isRestOfCompilation() {
+ return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF;
}
- /**
- * Constructor
- * @param paramTypes known parameter types for this callsite
- */
- public Hints(final Type[] paramTypes) {
- this.paramTypes = paramTypes;
+ String getDesc() {
+ return desc;
}
- /**
- * Get the parameter type for this parameter position, or
- * null if now known
- * @param pos position
- * @return parameter type for this callsite if known
- */
- public Type getParameterType(final int pos) {
- if (paramTypes != null && pos < paramTypes.length) {
- return paramTypes[pos];
+ String toString(final String prefix) {
+ final StringBuilder sb = new StringBuilder();
+ for (final CompilationPhase phase : phases) {
+ sb.append(prefix).append(phase).append('\n');
}
- return null;
+ return sb.toString();
}
}
/**
- * Standard (non-lazy) compilation, that basically will take an entire script
- * and JIT it at once. This can lead to long startup time and fewer type
- * specializations
+ * This array contains names that need to be reserved at the start
+ * of a compile, to avoid conflict with variable names later introduced.
+ * See {@link CompilerConstants} for special names used for structures
+ * during a compile.
*/
- final static CompilationSequence SEQUENCE_EAGER = new CompilationSequence(
- CompilationPhase.CONSTANT_FOLDING_PHASE,
- CompilationPhase.LOWERING_PHASE,
- CompilationPhase.ATTRIBUTION_PHASE,
- CompilationPhase.RANGE_ANALYSIS_PHASE,
- CompilationPhase.SPLITTING_PHASE,
- CompilationPhase.TYPE_FINALIZATION_PHASE,
- CompilationPhase.BYTECODE_GENERATION_PHASE);
-
- final static CompilationSequence SEQUENCE_LAZY =
- SEQUENCE_EAGER.insertFirst(CompilationPhase.LAZY_INITIALIZATION_PHASE);
+ private static String[] RESERVED_NAMES = {
+ SCOPE.symbolName(),
+ THIS.symbolName(),
+ RETURN.symbolName(),
+ CALLEE.symbolName(),
+ VARARGS.symbolName(),
+ ARGUMENTS.symbolName()
+ };
- private static CompilationSequence sequence(final boolean lazy) {
- return lazy ? SEQUENCE_LAZY : SEQUENCE_EAGER;
- }
+ // per instance
+ private final int compilationId = COMPILATION_ID.getAndIncrement();
- boolean isLazy() {
- return sequence == SEQUENCE_LAZY;
- }
+ // per instance
+ private final AtomicInteger nextCompileUnitId = new AtomicInteger(0);
- private static String lazyTag(final FunctionNode functionNode) {
- if (functionNode.isLazy()) {
- return '$' + LAZY.symbolName() + '$' + functionNode.getName();
- }
- return "";
- }
+ private static final AtomicInteger COMPILATION_ID = new AtomicInteger(0);
/**
* Constructor
*
- * @param env script environment
- * @param installer code installer
- * @param sequence {@link Compiler.CompilationSequence} of {@link CompilationPhase}s to apply as this compilation
- * @param strict should this compilation use strict mode semantics
+ * @param context context
+ * @param env script environment
+ * @param installer code installer
+ * @param source source to compile
+ * @param errors error manager
+ * @param isStrict is this a strict compilation
*/
- //TODO support an array of FunctionNodes for batch lazy compilation
- Compiler(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final CompilationSequence sequence, final boolean strict) {
- this.env = env;
- this.sequence = sequence;
- this.installer = installer;
- this.constantData = new ConstantData();
- this.compileUnits = new TreeSet<>();
- this.bytecode = new LinkedHashMap<>();
- }
-
- private void initCompiler(final FunctionNode functionNode) {
- this.strict = strict || functionNode.isStrict();
- final StringBuilder sb = new StringBuilder();
- sb.append(functionNode.uniqueName(DEFAULT_SCRIPT_NAME.symbolName() + lazyTag(functionNode))).
- append('$').
- append(safeSourceName(functionNode.getSource()));
- this.source = functionNode.getSource();
- this.sourceName = functionNode.getSourceName();
- this.scriptName = sb.toString();
+ public Compiler(
+ final Context context,
+ final ScriptEnvironment env,
+ final CodeInstaller<ScriptEnvironment> installer,
+ final Source source,
+ final ErrorManager errors,
+ final boolean isStrict) {
+ this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null);
}
/**
* Constructor
*
- * @param installer code installer
- * @param strict should this compilation use strict mode semantics
+ * @param context context
+ * @param env script environment
+ * @param installer code installer
+ * @param source source to compile
+ * @param errors error manager
+ * @param isStrict is this a strict compilation
+ * @param isOnDemand is this an on demand compilation
+ * @param compiledFunction compiled function, if any
+ * @param types parameter and return value type information, if any is known
+ * @param invalidatedProgramPoints invalidated program points for recompilation
+ * @param typeInformationFile descriptor of the location where type information is persisted
+ * @param continuationEntryPoints continuation entry points for restof method
+ * @param runtimeScope runtime scope for recompilation type lookup in {@code TypeEvaluator}
*/
- public Compiler(final CodeInstaller<ScriptEnvironment> installer, final boolean strict) {
- this(installer.getOwner(), installer, sequence(installer.getOwner()._lazy_compilation), strict);
+ @SuppressWarnings("unused")
+ public Compiler(
+ final Context context,
+ final ScriptEnvironment env,
+ final CodeInstaller<ScriptEnvironment> installer,
+ final Source source,
+ final ErrorManager errors,
+ final boolean isStrict,
+ final boolean isOnDemand,
+ final RecompilableScriptFunctionData compiledFunction,
+ final TypeMap types,
+ final Map<Integer, Type> invalidatedProgramPoints,
+ final Object typeInformationFile,
+ final int[] continuationEntryPoints,
+ final ScriptObject runtimeScope) {
+ this.context = context;
+ this.env = env;
+ this.installer = installer;
+ this.constantData = new ConstantData();
+ this.compileUnits = CompileUnit.createCompileUnitSet();
+ this.bytecode = new LinkedHashMap<>();
+ this.log = initLogger(context);
+ this.source = source;
+ this.errors = errors;
+ this.sourceName = FunctionNode.getSourceName(source);
+ this.onDemand = isOnDemand;
+ this.compiledFunction = compiledFunction;
+ this.types = types;
+ this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new HashMap<Integer, Type>() : invalidatedProgramPoints;
+ this.typeInformationFile = typeInformationFile;
+ this.continuationEntryPoints = continuationEntryPoints == null ? null: continuationEntryPoints.clone();
+ this.typeEvaluator = new TypeEvaluator(this, runtimeScope);
+ this.firstCompileUnitName = firstCompileUnitName();
+ this.strict = isStrict;
+
+ this.optimistic = env._optimistic_types;
+ }
+
+ private static String safeSourceName(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source) {
+ String baseName = new File(source.getName()).getName();
+
+ final int index = baseName.lastIndexOf(".js");
+ if (index != -1) {
+ baseName = baseName.substring(0, index);
+ }
+
+ baseName = baseName.replace('.', '_').replace('-', '_');
+ if (!env._loader_per_compile) {
+ baseName = baseName + installer.getUniqueScriptId();
+ }
+
+ // ASM's bytecode verifier does not allow JVM allowed safe escapes using '\' as escape char.
+ // While ASM accepts such escapes for method names, field names, it enforces Java identifier
+ // for class names. Workaround that ASM bug here by replacing JVM 'dangerous' chars with '_'
+ // rather than safe encoding using '\'.
+ final String mangled = env._verify_code? replaceDangerChars(baseName) : NameCodec.encode(baseName);
+ return mangled != null ? mangled : baseName;
}
- /**
- * Constructor - compilation will use the same strict semantics as in script environment
- *
- * @param installer code installer
- */
- public Compiler(final CodeInstaller<ScriptEnvironment> installer) {
- this(installer.getOwner(), installer, sequence(installer.getOwner()._lazy_compilation), installer.getOwner()._strict);
+ private static final String DANGEROUS_CHARS = "\\/.;:$[]<>";
+ private static String replaceDangerChars(final String name) {
+ final int len = name.length();
+ final StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < len; i++) {
+ final char ch = name.charAt(i);
+ if (DANGEROUS_CHARS.indexOf(ch) != -1) {
+ buf.append('_');
+ } else {
+ buf.append(ch);
+ }
+ }
+ return buf.toString();
}
- /**
- * Constructor - compilation needs no installer, but uses a script environment
- * Used in "compile only" scenarios
- * @param env a script environment
- */
- public Compiler(final ScriptEnvironment env) {
- this(env, null, sequence(env._lazy_compilation), env._strict);
+ private String firstCompileUnitName() {
+ final StringBuilder sb = new StringBuilder(SCRIPTS_PACKAGE).
+ append('/').
+ append(CompilerConstants.DEFAULT_SCRIPT_NAME.symbolName()).
+ append('$');
+
+ if (isOnDemandCompilation()) {
+ sb.append(RecompilableScriptFunctionData.RECOMPILATION_PREFIX);
+ }
+
+ if (compilationId > 0) {
+ sb.append(compilationId).append('$');
+ }
+
+ if (types != null && compiledFunction.getFunctionNodeId() > 0) {
+ sb.append(compiledFunction.getFunctionNodeId());
+ final Type[] paramTypes = types.getParameterTypes(compiledFunction.getFunctionNodeId());
+ for (final Type t : paramTypes) {
+ sb.append(Type.getShortSignatureDescriptor(t));
+ }
+ sb.append('$');
+ }
+
+ sb.append(Compiler.safeSourceName(env, installer, source));
+
+ return sb.toString();
}
- private static void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
- LOG.info(phaseName + " finished. Doing IR size calculation...");
+ void declareLocalSymbol(final String symbolName) {
+ typeEvaluator.declareLocalSymbol(symbolName);
+ }
- final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
- osc.calculateObjectSize(functionNode);
+ void setData(final RecompilableScriptFunctionData data) {
+ assert this.compiledFunction == null : data;
+ this.compiledFunction = data;
+ }
- final List<ClassHistogramElement> list = osc.getClassHistogram();
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
- final StringBuilder sb = new StringBuilder();
- final long totalSize = osc.calculateObjectSize(functionNode);
- sb.append(phaseName).append(" Total size = ").append(totalSize / 1024 / 1024).append("MB");
- LOG.info(sb);
+ @Override
+ public DebugLogger initLogger(final Context ctxt) {
+ final boolean optimisticTypes = env._optimistic_types;
+ final boolean lazyCompilation = env._lazy_compilation;
- Collections.sort(list, new Comparator<ClassHistogramElement>() {
+ return ctxt.getLogger(this.getClass(), new Consumer<DebugLogger>() {
@Override
- public int compare(ClassHistogramElement o1, ClassHistogramElement o2) {
- final long diff = o1.getBytes() - o2.getBytes();
- if (diff < 0) {
- return 1;
- } else if (diff > 0) {
- return -1;
- } else {
- return 0;
+ public void accept(final DebugLogger newLogger) {
+ if (!lazyCompilation) {
+ newLogger.warning("WARNING: Running with lazy compilation switched off. This is not a default setting.");
}
+ newLogger.warning("Optimistic types are ", optimisticTypes ? "ENABLED." : "DISABLED.");
}
});
- for (final ClassHistogramElement e : list) {
- final String line = String.format(" %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
- LOG.info(line);
- if (e.getBytes() < totalSize / 200) {
- LOG.info(" ...");
- break; // never mind, so little memory anyway
- }
- }
}
- /**
- * Execute the compilation this Compiler was created with
- * @param functionNode function node to compile from its current state
- * @throws CompilationException if something goes wrong
- * @return function node that results from code transforms
- */
- public FunctionNode compile(final FunctionNode functionNode) throws CompilationException {
- FunctionNode newFunctionNode = functionNode;
-
- initCompiler(newFunctionNode); //TODO move this state into functionnode?
+ ScriptEnvironment getScriptEnvironment() {
+ return env;
+ }
- for (final String reservedName : RESERVED_NAMES) {
- newFunctionNode.uniqueName(reservedName);
- }
+ boolean isOnDemandCompilation() {
+ return onDemand;
+ }
- final boolean fine = !LOG.levelAbove(Level.FINE);
- final boolean info = !LOG.levelAbove(Level.INFO);
+ boolean useOptimisticTypes() {
+ return optimistic;
+ }
- long time = 0L;
+ Context getContext() {
+ return context;
+ }
- for (final CompilationPhase phase : sequence) {
- newFunctionNode = phase.apply(this, newFunctionNode);
+ Type getOptimisticType(final Optimistic node) {
+ return typeEvaluator.getOptimisticType(node);
+ }
- if (env._print_mem_usage) {
- printMemoryUsage(phase.toString(), newFunctionNode);
- }
+ /**
+ * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+ * String as the type of its property names retrieved through
+ * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+ * property name types.
+ * @param expr the expression to test
+ * @return true if the expression can be safely evaluated, and its value is an object known to always use
+ * String as the type of its property iterators.
+ */
+ boolean hasStringPropertyIterator(final Expression expr) {
+ return typeEvaluator.hasStringPropertyIterator(expr);
+ }
- final long duration = Timing.isEnabled() ? (phase.getEndTime() - phase.getStartTime()) : 0L;
- time += duration;
+ void addInvalidatedProgramPoint(final int programPoint, final Type type) {
+ invalidatedProgramPoints.put(programPoint, type);
+ }
- if (fine) {
- final StringBuilder sb = new StringBuilder();
- sb.append(phase.toString()).
- append(" done for function '").
- append(newFunctionNode.getName()).
- append('\'');
+ /**
+ * Returns a copy of this compiler's current mapping of invalidated optimistic program points to their types. The
+ * copy is not live with regard to changes in state in this compiler instance, and is mutable.
+ * @return a copy of this compiler's current mapping of invalidated optimistic program points to their types.
+ */
+ public Map<Integer, Type> getInvalidatedProgramPoints() {
+ return invalidatedProgramPoints == null ? null : new TreeMap<>(invalidatedProgramPoints);
+ }
- if (duration > 0L) {
- sb.append(" in ").
- append(duration).
- append(" ms ");
- }
+ TypeMap getTypeMap() {
+ return types;
+ }
- LOG.fine(sb);
- }
+ MethodType getCallSiteType(final FunctionNode fn) {
+ if (types == null || !isOnDemandCompilation()) {
+ return null;
}
+ return types.getCallSiteType(fn);
+ }
- if (info) {
- final StringBuilder sb = new StringBuilder();
- sb.append("Compile job for '").
- append(newFunctionNode.getSource()).
- append(':').
- append(newFunctionNode.getName()).
- append("' finished");
+ Type getParamType(final FunctionNode fn, final int pos) {
+ return types == null ? null : types.get(fn, pos);
+ }
- if (time > 0L) {
- sb.append(" in ").
- append(time).
- append(" ms");
- }
+ /**
+ * Do a compilation job
+ *
+ * @param functionNode function node to compile
+ * @param phases phases of compilation transforms to apply to function
- LOG.info(sb);
+ * @return transformed function
+ *
+ * @throws CompilationException if error occurs during compilation
+ */
+ public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException {
+ if (log.isEnabled()) {
+ log.info(">> Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
+ log.indent();
}
- return newFunctionNode;
- }
+ final String name = DebugLogger.quote(functionNode.getName());
- private Class<?> install(final String className, final byte[] code, final Object[] constants) {
- return installer.install(className, code, source, constants);
- }
+ FunctionNode newFunctionNode = functionNode;
- /**
- * Install compiled classes into a given loader
- * @param functionNode function node to install - must be in {@link CompilationState#EMITTED} state
- * @return root script class - if there are several compile units they will also be installed
- */
- public Class<?> install(final FunctionNode functionNode) {
- final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
+ for (final String reservedName : RESERVED_NAMES) {
+ newFunctionNode.uniqueName(reservedName);
+ }
- assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
+ final boolean info = log.levelFinerThanOrEqual(Level.INFO);
- final Map<String, Class<?>> installedClasses = new HashMap<>();
- final Object[] constants = getConstantData().toArray();
+ final DebugLogger timeLogger = env.isTimingEnabled() ? env._timing.getLogger() : null;
- final String rootClassName = firstCompileUnitName();
- final byte[] rootByteCode = bytecode.get(rootClassName);
- final Class<?> rootClass = install(rootClassName, rootByteCode, constants);
+ long time = 0L;
- if (!isLazy()) {
- installer.storeCompiledScript(source, rootClassName, bytecode, constants);
- }
+ for (final CompilationPhase phase : phases) {
+ log.fine(phase, " starting for ", name);
- int length = rootByteCode.length;
+ try {
+ newFunctionNode = phase.apply(this, phases, newFunctionNode);
+ } catch (final ParserException error) {
+ errors.error(error);
+ if (env._dump_on_error) {
+ error.printStackTrace(env.getErr());
+ }
+ return null;
+ }
- installedClasses.put(rootClassName, rootClass);
+ log.fine(phase, " done for function ", quote(name));
- for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
- final String className = entry.getKey();
- if (className.equals(rootClassName)) {
- continue;
+ if (env._print_mem_usage) {
+ printMemoryUsage(functionNode, phase.toString());
}
- final byte[] code = entry.getValue();
- length += code.length;
- installedClasses.put(className, install(className, code, constants));
+ time += (env.isTimingEnabled() ? phase.getEndTime() - phase.getStartTime() : 0L);
}
- for (final CompileUnit unit : compileUnits) {
- unit.setCode(installedClasses.get(unit.getUnitClassName()));
- }
-
- final StringBuilder sb;
- if (LOG.isEnabled()) {
- sb = new StringBuilder();
- sb.append("Installed class '").
- append(rootClass.getSimpleName()).
- append('\'').
- append(" bytes=").
- append(length).
- append('.');
- if (bytecode.size() > 1) {
- sb.append(' ').append(bytecode.size()).append(" compile units.");
- }
- } else {
- sb = null;
+ if (typeInformationFile != null && !phases.isRestOfCompilation()) {
+ OptimisticTypesPersistence.store(typeInformationFile, invalidatedProgramPoints);
}
- if (Timing.isEnabled()) {
- final long duration = System.currentTimeMillis() - t0;
- Timing.accumulateTime("[Code Installation]", duration);
- if (sb != null) {
- sb.append(" Install time: ").append(duration).append(" ms");
+ log.unindent();
+
+ if (info) {
+ final StringBuilder sb = new StringBuilder("<< Finished compile job for ");
+ sb.append(newFunctionNode.getSource()).
+ append(':').
+ append(quote(newFunctionNode.getName()));
+
+ if (time > 0L && timeLogger != null) {
+ assert env.isTimingEnabled();
+ sb.append(" in ").append(time).append(" ms");
}
+ log.info(sb);
}
- if (sb != null) {
- LOG.fine(sb);
- }
+ return newFunctionNode;
+ }
- return rootClass;
+ Source getSource() {
+ return source;
}
- Set<CompileUnit> getCompileUnits() {
- return compileUnits;
+ Map<String, byte[]> getBytecode() {
+ return Collections.unmodifiableMap(bytecode);
}
- boolean getStrictMode() {
- return strict;
+ /**
+ * Reset bytecode cache for compiler reuse.
+ */
+ void clearBytecode() {
+ bytecode.clear();
}
- void setStrictMode(final boolean strict) {
- this.strict = strict;
+ CompileUnit getFirstCompileUnit() {
+ assert !compileUnits.isEmpty();
+ return compileUnits.iterator().next();
+ }
+
+ Set<CompileUnit> getCompileUnits() {
+ return compileUnits;
}
ConstantData getConstantData() {
@@ -500,76 +689,102 @@ public final class Compiler {
return installer;
}
- TemporarySymbols getTemporarySymbols() {
- return temporarySymbols;
- }
-
void addClass(final String name, final byte[] code) {
bytecode.put(name, code);
}
- ScriptEnvironment getEnv() {
- return this.env;
+ String nextCompileUnitName() {
+ final StringBuilder sb = new StringBuilder(COMPILE_UNIT_NAME_BUFFER_SIZE);
+ sb.append(firstCompileUnitName);
+ final int cuid = nextCompileUnitId.getAndIncrement();
+ if (cuid > 0) {
+ sb.append("$cu").append(cuid);
+ }
+
+ return sb.toString();
}
- private String safeSourceName(final Source src) {
- String baseName = new File(src.getName()).getName();
+ Map<Integer, FunctionInitializer> functionInitializers;
- final int index = baseName.lastIndexOf(".js");
- if (index != -1) {
- baseName = baseName.substring(0, index);
+ void addFunctionInitializer(final RecompilableScriptFunctionData functionData, final FunctionNode functionNode) {
+ if (functionInitializers == null) {
+ functionInitializers = new HashMap<>();
}
-
- baseName = baseName.replace('.', '_').replace('-', '_');
- if (! env._loader_per_compile) {
- baseName = baseName + installer.getUniqueScriptId();
+ if (!functionInitializers.containsKey(functionData)) {
+ functionInitializers.put(functionData.getFunctionNodeId(), new FunctionInitializer(functionNode));
}
- final String mangled = NameCodec.encode(baseName);
-
- return mangled != null ? mangled : baseName;
}
- private int nextCompileUnitIndex() {
- return compileUnits.size() + 1;
+ Map<Integer, FunctionInitializer> getFunctionInitializers() {
+ return functionInitializers;
}
- String firstCompileUnitName() {
- return SCRIPTS_PACKAGE + '/' + scriptName;
+ /**
+ * Persist current compilation with the given {@code cacheKey}.
+ * @param cacheKey cache key
+ * @param functionNode function node
+ */
+ public void persistClassInfo(final String cacheKey, final FunctionNode functionNode) {
+ if (cacheKey != null && env._persistent_cache) {
+ Map<Integer, FunctionInitializer> initializers;
+ // If this is an on-demand compilation create a function initializer for the function being compiled.
+ // Otherwise use function initializer map generated by codegen.
+ if (functionInitializers == null) {
+ initializers = new HashMap<>();
+ final FunctionInitializer initializer = new FunctionInitializer(functionNode, getInvalidatedProgramPoints());
+ initializers.put(functionNode.getId(), initializer);
+ } else {
+ initializers = functionInitializers;
+ }
+ final String mainClassName = getFirstCompileUnit().getUnitClassName();
+ installer.storeScript(cacheKey, source, mainClassName, bytecode, initializers, constantData.toArray(), compilationId);
+ }
}
- private String nextCompileUnitName() {
- return firstCompileUnitName() + '$' + nextCompileUnitIndex();
+ /**
+ * Make sure the next compilation id is greater than {@code value}.
+ * @param value compilation id value
+ */
+ public static void updateCompilationId(final int value) {
+ if (value >= COMPILATION_ID.get()) {
+ COMPILATION_ID.set(value + 1);
+ }
}
CompileUnit addCompileUnit(final long initialWeight) {
- return addCompileUnit(nextCompileUnitName(), initialWeight);
+ final CompileUnit compileUnit = createCompileUnit(initialWeight);
+ compileUnits.add(compileUnit);
+ log.fine("Added compile unit ", compileUnit);
+ return compileUnit;
}
- CompileUnit addCompileUnit(final String unitClassName) {
- return addCompileUnit(unitClassName, 0L);
- }
+ CompileUnit createCompileUnit(final String unitClassName, final long initialWeight) {
+ final ClassEmitter classEmitter = new ClassEmitter(context, sourceName, unitClassName, isStrict());
+ final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight);
+ classEmitter.begin();
- private CompileUnit addCompileUnit(final String unitClassName, final long initialWeight) {
- final CompileUnit compileUnit = initCompileUnit(unitClassName, initialWeight);
- compileUnits.add(compileUnit);
- LOG.fine("Added compile unit ", compileUnit);
return compileUnit;
}
- private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) {
- final ClassEmitter classEmitter = new ClassEmitter(env, sourceName, unitClassName, strict);
- final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight);
+ private CompileUnit createCompileUnit(final long initialWeight) {
+ return createCompileUnit(nextCompileUnitName(), initialWeight);
+ }
- classEmitter.begin();
+ boolean isStrict() {
+ return strict;
+ }
- final MethodEmitter initMethod = classEmitter.init(EnumSet.of(Flag.PRIVATE));
- initMethod.begin();
- initMethod.load(Type.OBJECT, 0);
- initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class);
- initMethod.returnVoid();
- initMethod.end();
+ void replaceCompileUnits(final Set<CompileUnit> newUnits) {
+ compileUnits.clear();
+ compileUnits.addAll(newUnits);
+ }
- return compileUnit;
+ void serializeAst(final FunctionNode fn) {
+ serializedAsts.put(fn.getId(), AstSerializer.serialize(fn));
+ }
+
+ byte[] removeSerializedAst(final int fnId) {
+ return serializedAsts.remove(fnId);
}
CompileUnit findUnit(final long weight) {
@@ -593,22 +808,65 @@ public final class Compiler {
return name.replace('/', '.');
}
- /**
- * Should we use integers for arithmetic operations as well?
- * TODO: We currently generate no overflow checks so this is
- * disabled
- *
- * @return true if arithmetic operations should not widen integer
- * operands by default.
- */
- static boolean shouldUseIntegerArithmetic() {
- return USE_INT_ARITH;
+ RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
+ assert compiledFunction != null;
+ final RecompilableScriptFunctionData fn = compiledFunction.getScriptFunctionData(functionId);
+ assert fn != null : functionId;
+ return fn;
}
- private static final boolean USE_INT_ARITH;
+ boolean isGlobalSymbol(final FunctionNode fn, final String name) {
+ return getScriptFunctionData(fn.getId()).isGlobalSymbol(fn, name);
+ }
- static {
- USE_INT_ARITH = Options.getBooleanProperty("nashorn.compiler.intarithmetic");
- assert !USE_INT_ARITH : "Integer arithmetic is not enabled";
+ int[] getContinuationEntryPoints() {
+ return continuationEntryPoints;
+ }
+
+ Type getInvalidatedProgramPointType(final int programPoint) {
+ return invalidatedProgramPoints.get(programPoint);
+ }
+
+ private void printMemoryUsage(final FunctionNode functionNode, final String phaseName) {
+ if (!log.isEnabled()) {
+ return;
+ }
+
+ log.info(phaseName, "finished. Doing IR size calculation...");
+
+ final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
+ osc.calculateObjectSize(functionNode);
+
+ final List<ClassHistogramElement> list = osc.getClassHistogram();
+ final StringBuilder sb = new StringBuilder();
+ final long totalSize = osc.calculateObjectSize(functionNode);
+
+ sb.append(phaseName).
+ append(" Total size = ").
+ append(totalSize / 1024 / 1024).
+ append("MB");
+ log.info(sb);
+
+ Collections.sort(list, new Comparator<ClassHistogramElement>() {
+ @Override
+ public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
+ final long diff = o1.getBytes() - o2.getBytes();
+ if (diff < 0) {
+ return 1;
+ } else if (diff > 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ });
+ for (final ClassHistogramElement e : list) {
+ final String line = String.format(" %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
+ log.info(line);
+ if (e.getBytes() < totalSize / 200) {
+ log.info(" ...");
+ break; // never mind, so little memory anyway
+ }
+ }
}
}
diff --git a/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index 16f08b82..e84c9f04 100644
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -29,7 +29,11 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -41,7 +45,6 @@ import jdk.nashorn.internal.runtime.Source;
*/
public enum CompilerConstants {
-
/** the __FILE__ variable */
__FILE__,
@@ -51,9 +54,6 @@ public enum CompilerConstants {
/** the __LINE__ variable */
__LINE__,
- /** lazy prefix for classes of jitted methods */
- LAZY("Lazy"),
-
/** constructor name */
INIT("<init>"),
@@ -78,15 +78,18 @@ public enum CompilerConstants {
/** function prefix for anonymous functions */
ANON_FUNCTION_PREFIX("L:"),
- /** method name for Java method that is script entry point */
- RUN_SCRIPT("runScript"),
+ /** method name for Java method that is the program entry point */
+ PROGRAM(":program"),
+
+ /** method name for Java method that creates the script function for the program */
+ CREATE_PROGRAM_FUNCTION(":createProgramFunction"),
/**
* "this" name symbol for a parameter representing ECMAScript "this" in static methods that are compiled
* representations of ECMAScript functions. It is not assigned a slot, as its position in the method signature is
* dependent on other factors (most notably, callee can precede it).
*/
- THIS("this"),
+ THIS("this", Object.class),
/** this debugger symbol */
THIS_DEBUGGER(":this"),
@@ -110,13 +113,16 @@ public enum CompilerConstants {
/** the internal arguments object, when necessary (not visible to scripts, can't be reassigned). */
ARGUMENTS(":arguments", ScriptObject.class),
+ /** prefix for apply-to-call exploded arguments */
+ EXPLODED_ARGUMENT_PREFIX(":xarg"),
+
/** prefix for iterators for for (x in ...) */
ITERATOR_PREFIX(":i", Iterator.class),
/** prefix for tag variable used for switch evaluation */
SWITCH_TAG_PREFIX(":s"),
- /** prefix for all exceptions */
+ /** prefix for JVM exceptions */
EXCEPTION_PREFIX(":e", Throwable.class),
/** prefix for quick slots generated in Store */
@@ -161,7 +167,7 @@ public enum CompilerConstants {
/** get map */
GET_MAP(":getMap"),
- /** get map */
+ /** set map */
SET_MAP(":setMap"),
/** get array prefix */
@@ -170,10 +176,22 @@ public enum CompilerConstants {
/** get array suffix */
GET_ARRAY_SUFFIX("$array");
+ /** To save memory - intern the compiler constant symbol names, as they are frequently reused */
+ static {
+ for (final CompilerConstants c : values()) {
+ final String symbolName = c.symbolName();
+ if (symbolName != null) {
+ symbolName.intern();
+ }
+ }
+ }
+
+ private static Set<String> symbolNames;
+
/**
* Prefix used for internal methods generated in script clases.
*/
- public static final String INTERNAL_METHOD_PREFIX = ":";
+ private static final String INTERNAL_METHOD_PREFIX = ":";
private final String symbolName;
private final Class<?> type;
@@ -198,9 +216,28 @@ public enum CompilerConstants {
}
private CompilerConstants(final String symbolName, final Class<?> type, final int slot) {
- this.symbolName = symbolName;
- this.type = type;
- this.slot = slot;
+ this.symbolName = symbolName;
+ this.type = type;
+ this.slot = slot;
+ }
+
+ /**
+ * Check whether a name is that of a reserved compiler constnat
+ * @param name name
+ * @return true if compiler constant name
+ */
+ public static boolean isCompilerConstant(final String name) {
+ ensureSymbolNames();
+ return symbolNames.contains(name);
+ }
+
+ private static void ensureSymbolNames() {
+ if(symbolNames == null) {
+ symbolNames = new HashSet<>();
+ for(final CompilerConstants cc: CompilerConstants.values()) {
+ symbolNames.add(cc.symbolName);
+ }
+ }
}
/**
@@ -327,9 +364,14 @@ public enum CompilerConstants {
public static Call specialCallNoLookup(final String className, final String name, final String desc) {
return new Call(null, className, name, desc) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokespecial(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, desc, false);
+ }
};
}
@@ -361,9 +403,14 @@ public enum CompilerConstants {
public static Call staticCallNoLookup(final String className, final String name, final String desc) {
return new Call(null, className, name, desc) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokestatic(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, desc, false);
+ }
};
}
@@ -396,9 +443,14 @@ public enum CompilerConstants {
public static Call virtualCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokevirtual(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
+ }
};
}
@@ -416,9 +468,14 @@ public enum CompilerConstants {
public static Call interfaceCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokeinterface(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, name, descriptor, true);
+ }
};
}
@@ -512,9 +569,14 @@ public enum CompilerConstants {
public static Call staticCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokestatic(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, descriptor, false);
+ }
};
}
@@ -532,13 +594,56 @@ public enum CompilerConstants {
public static Call virtualCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
@Override
- public MethodEmitter invoke(final MethodEmitter method) {
+ MethodEmitter invoke(final MethodEmitter method) {
return method.invokevirtual(className, name, descriptor);
}
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
+ }
};
}
/**
+ * Create a special call, given an explicit lookup, looking up the method handle for it at the same time.
+ * clazz is used as this class
+ *
+ * @param lookup the lookup
+ * @param clazz the class
+ * @param name the name of the method
+ * @param rtype the return type
+ * @param ptypes the parameter types
+ *
+ * @return the call object representing the virtual call
+ */
+ public static Call specialCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
+ return new Call(MH.findSpecial(lookup, clazz, name, MH.type(rtype, ptypes), clazz), className(clazz), name, methodDescriptor(rtype, ptypes)) {
+ @Override
+ MethodEmitter invoke(final MethodEmitter method) {
+ return method.invokespecial(className, name, descriptor);
+ }
+
+ @Override
+ public void invoke(final MethodVisitor mv) {
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, descriptor, false);
+ }
+ };
+ }
+
+ /**
+ * Returns true if the passed string looks like a method name of an internally generated Nashorn method. Basically,
+ * if it starts with a colon character {@code :} but is not the name of the program method {@code :program}.
+ * Program function is not considered internal as we want it to show up in exception stack traces.
+ * @param methodName the name of a method
+ * @return true if it looks like an internal Nashorn method name.
+ * @throws NullPointerException if passed null
+ */
+ public static boolean isInternalMethodName(final String methodName) {
+ return methodName.startsWith(INTERNAL_METHOD_PREFIX) && !methodName.equals(PROGRAM.symbolName);
+ }
+
+ /**
* Private class representing an access. This can generate code into a method code or
* a field access.
*/
@@ -668,7 +773,14 @@ public enum CompilerConstants {
*
* @return the method emitter
*/
- protected abstract MethodEmitter invoke(final MethodEmitter emitter);
+ abstract MethodEmitter invoke(final MethodEmitter emitter);
+
+ /**
+ * Generate invocation code for the method
+ *
+ * @param mv a method visitor
+ */
+ public abstract void invoke(final MethodVisitor mv);
}
}
diff --git a/src/jdk/nashorn/internal/codegen/Condition.java b/src/jdk/nashorn/internal/codegen/Condition.java
index 80ed029c..27402ed8 100644
--- a/src/jdk/nashorn/internal/codegen/Condition.java
+++ b/src/jdk/nashorn/internal/codegen/Condition.java
@@ -66,8 +66,7 @@ enum Condition {
case GT:
return IFGT;
default:
- assert false;
- return -1;
+ throw new UnsupportedOperationException("toUnary:" + c.toString());
}
}
@@ -86,8 +85,7 @@ enum Condition {
case GT:
return IF_ICMPGT;
default:
- assert false;
- return -1;
+ throw new UnsupportedOperationException("toBinary:" + c.toString());
}
}
}
diff --git a/src/jdk/nashorn/internal/codegen/ConstantData.java b/src/jdk/nashorn/internal/codegen/ConstantData.java
index 292f1678..cd87f0f6 100644
--- a/src/jdk/nashorn/internal/codegen/ConstantData.java
+++ b/src/jdk/nashorn/internal/codegen/ConstantData.java
@@ -25,20 +25,18 @@
package jdk.nashorn.internal.codegen;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import jdk.nashorn.internal.runtime.PropertyMap;
/**
* Manages constants needed by code generation. Objects are maintained in an
* interning maps to remove duplicates.
*/
-class ConstantData {
+final class ConstantData {
/** Constant table. */
final List<Object> constants;
@@ -64,7 +62,7 @@ class ConstantData {
private int calcHashCode() {
final Class<?> cls = array.getClass();
- if (cls == Object[].class) {
+ if (!cls.getComponentType().isPrimitive()) {
return Arrays.hashCode((Object[])array);
} else if (cls == double[].class) {
return Arrays.hashCode((double[])array);
@@ -92,7 +90,7 @@ class ConstantData {
final Class<?> cls = array.getClass();
if (cls == otherArray.getClass()) {
- if (cls == Object[].class) {
+ if (!cls.getComponentType().isPrimitive()) {
return Arrays.equals((Object[])array, (Object[])otherArray);
} else if (cls == double[].class) {
return Arrays.equals((double[])array, (double[])otherArray);
@@ -122,12 +120,7 @@ class ConstantData {
private final int hashCode;
public PropertyMapWrapper(final PropertyMap map) {
- int hash = 0;
- for (final Property property : map.getProperties()) {
- hash = hash << 7 ^ hash >> 7;
- hash ^= property.hashCode();
- }
- this.hashCode = hash;
+ this.hashCode = Arrays.hashCode(map.getProperties());
this.propertyMap = map;
}
@@ -138,14 +131,8 @@ class ConstantData {
@Override
public boolean equals(final Object other) {
- if (!(other instanceof PropertyMapWrapper)) {
- return false;
- }
-
- final Property[] ownProperties = propertyMap.getProperties();
- final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
-
- return Arrays.equals(ownProperties, otherProperties);
+ return other instanceof PropertyMapWrapper &&
+ Arrays.equals(propertyMap.getProperties(), ((PropertyMapWrapper) other).propertyMap.getProperties());
}
}
@@ -185,6 +172,7 @@ class ConstantData {
* @return the index in the constant pool that the object was given
*/
public int add(final Object object) {
+ assert object != null;
final Object entry;
if (object.getClass().isArray()) {
entry = new ArrayWrapper(object);
diff --git a/src/jdk/nashorn/internal/codegen/DumpBytecode.java b/src/jdk/nashorn/internal/codegen/DumpBytecode.java
new file mode 100644
index 00000000..e6773821
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/DumpBytecode.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+
+/**
+ * Class that facilitates printing bytecode and dumping it to disk.
+ */
+public final class DumpBytecode {
+ /**
+ * Dump bytecode to console and potentially disk.
+ * @param env the script environment defining options for printing bytecode
+ * @param logger a logger used to write diagnostics about bytecode dumping
+ * @param bytecode the actual code to dump
+ * @param className the name of the class being dumped
+ */
+ public static void dumpBytecode(final ScriptEnvironment env, final DebugLogger logger, final byte[] bytecode, final String className) {
+ File dir = null;
+ try {
+ // should could be printed to stderr for generate class?
+ if (env._print_code) {
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append("class: " + className).
+ append('\n').
+ append(ClassEmitter.disassemble(bytecode)).
+ append("=====");
+
+ if (env._print_code_dir != null) {
+
+ String name = className;
+ final int dollar = name.lastIndexOf('$');
+ if (dollar != -1) {
+ name = name.substring(dollar + 1);
+ }
+
+ dir = new File(env._print_code_dir);
+ if (!dir.exists() && !dir.mkdirs()) {
+ throw new IOException(dir.toString());
+ }
+
+ File file;
+ String fileName;
+ int uniqueId = 0;
+ do {
+ fileName = name + (uniqueId == 0 ? "" : "_" + uniqueId) + ".bytecode";
+ file = new File(env._print_code_dir, fileName);
+ uniqueId++;
+ } while (file.exists());
+
+ try (final PrintWriter pw = new PrintWriter(new FileOutputStream(file))) {
+ pw.print(sb.toString());
+ pw.flush();
+ }
+ } else {
+ env.getErr().println(sb);
+ }
+ }
+
+
+ // should code be dumped to disk - only valid in compile_only mode?
+ if (env._dest_dir != null) {
+ final String fileName = className.replace('.', File.separatorChar) + ".class";
+ final int index = fileName.lastIndexOf(File.separatorChar);
+
+ if (index != -1) {
+ dir = new File(env._dest_dir, fileName.substring(0, index));
+ } else {
+ dir = new File(env._dest_dir);
+ }
+
+ if (!dir.exists() && !dir.mkdirs()) {
+ throw new IOException(dir.toString());
+ }
+ final File file = new File(env._dest_dir, fileName);
+ try (final FileOutputStream fos = new FileOutputStream(file)) {
+ fos.write(bytecode);
+ }
+ logger.info("Wrote class to '" + file.getAbsolutePath() + '\'');
+ }
+ } catch (final IOException e) {
+ logger.warning("Skipping class dump for ",
+ className,
+ ": ",
+ ECMAErrors.getMessage(
+ "io.error.cant.write",
+ dir.toString()));
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
index 438103e3..491af86f 100644
--- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
@@ -28,8 +28,9 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount;
-import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
@@ -51,47 +52,41 @@ import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
* @param <T> the value type for the fields being written on object creation, e.g. Node
* @see jdk.nashorn.internal.ir.Node
*/
-public abstract class FieldObjectCreator<T> extends ObjectCreator {
+public abstract class FieldObjectCreator<T> extends ObjectCreator<T> {
- private String fieldObjectClassName;
- private Class<?> fieldObjectClass;
- private int fieldCount;
- private int paddedFieldCount;
- private int paramCount;
-
- /** array of corresponding values to symbols (null for no values) */
- private final List<T> values;
+ private String fieldObjectClassName;
+ private Class<? extends ScriptObject> fieldObjectClass;
+ private int fieldCount;
+ private int paddedFieldCount;
+ private int paramCount;
/** call site flags to be used for invocations */
- private final int callSiteFlags;
+ private final int callSiteFlags;
+ /** are we creating this field object from 'eval' code? */
+ private final boolean evalCode;
/**
* Constructor
*
* @param codegen code generator
- * @param keys keys for fields in object
- * @param symbols symbols for fields in object
- * @param values list of values corresponding to keys
+ * @param tuples tuples for fields in object
*/
- FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values) {
- this(codegen, keys, symbols, values, false, false);
+ FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples) {
+ this(codegen, tuples, false, false);
}
/**
* Constructor
*
* @param codegen code generator
- * @param keys keys for fields in object
- * @param symbols symbols for fields in object
- * @param values values (or null where no value) to be written to the fields
+ * @param tuples tuples for fields in object
* @param isScope is this a scope object
* @param hasArguments does the created object have an "arguments" property
*/
- FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values, final boolean isScope, final boolean hasArguments) {
- super(codegen, keys, symbols, isScope, hasArguments);
- this.values = values;
+ FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) {
+ super(codegen, tuples, isScope, hasArguments);
this.callSiteFlags = codegen.getCallSiteFlags();
-
+ this.evalCode = codegen.isEvalCode();
countFields();
findClass();
}
@@ -104,8 +99,19 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
@Override
protected void makeObject(final MethodEmitter method) {
makeMap();
-
- method._new(getClassName()).dup(); // create instance
+ final String className = getClassName();
+ try {
+ // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
+ // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
+ // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
+ // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
+ // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
+ // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
+ // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
+ method._new(Context.forStructureClass(className.replace('/', '.'))).dup();
+ } catch (final ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
loadMap(method); //load the map
if (isScope()) {
@@ -113,32 +119,31 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
if (hasArguments()) {
method.loadCompilerConstant(ARGUMENTS);
- method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class, ARGUMENTS.type()));
+ method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class, ARGUMENTS.type()));
} else {
- method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class));
+ method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class));
}
} else {
- method.invoke(constructorNoLookup(getClassName(), PropertyMap.class));
+ method.invoke(constructorNoLookup(className, PropertyMap.class));
}
// Set values.
- final Iterator<Symbol> symbolIter = symbols.iterator();
- final Iterator<String> keyIter = keys.iterator();
- final Iterator<T> valueIter = values.iterator();
-
- while (symbolIter.hasNext()) {
- final Symbol symbol = symbolIter.next();
- final String key = keyIter.next();
- final T value = valueIter.next();
-
- if (symbol != null && value != null) {
- final int index = getArrayIndex(key);
-
+ final Iterator<MapTuple<T>> iter = tuples.iterator();
+
+ while (iter.hasNext()) {
+ final MapTuple<T> tuple = iter.next();
+ //we only load when we have both symbols and values (which can be == the symbol)
+ //if we didn't load, we need an array property
+ if (tuple.symbol != null && tuple.value != null) {
+ final int index = getArrayIndex(tuple.key);
if (!isValidArrayIndex(index)) {
- putField(method, key, symbol.getFieldIndex(), value);
+ putField(method, tuple.key, tuple.symbol.getFieldIndex(), tuple);
} else {
- putSlot(method, ArrayIndex.toLongIndex(index), value);
+ putSlot(method, ArrayIndex.toLongIndex(index), tuple);
}
+
+ //this is a nop of tuple.key isn't e.g. "apply" or another special name
+ method.invalidateSpecialName(tuple.key);
}
}
}
@@ -146,31 +151,32 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
@Override
protected PropertyMap makeMap() {
assert propertyMap == null : "property map already initialized";
- propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), fieldCount, paddedFieldCount);
+ propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), fieldCount, paddedFieldCount, evalCode);
return propertyMap;
}
/**
- * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
- *
- * @param value Value to load.
- */
- protected abstract void loadValue(T value);
-
- /**
* Store a value in a field of the generated class object.
*
* @param method Script method.
* @param key Property key.
* @param fieldIndex Field number.
- * @param value Value to store.
+ * @param tuple Tuple to store.
*/
- private void putField(final MethodEmitter method, final String key, final int fieldIndex, final T value) {
+ private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) {
method.dup();
- loadValue(value);
- method.convert(OBJECT);
- method.putField(getClassName(), ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT), typeDescriptor(Object.class));
+ final Type fieldType = tuple.isPrimitive() ? PRIMITIVE_FIELD_TYPE : Type.OBJECT;
+ final String fieldClass = getClassName();
+ final String fieldName = getFieldName(fieldIndex, fieldType);
+ final String fieldDesc = typeDescriptor(fieldType.getTypeClass());
+
+ assert fieldName.equals(getFieldName(fieldIndex, PRIMITIVE_FIELD_TYPE)) || fieldType.isObject() : key + " object keys must store to L*-fields";
+ assert fieldName.equals(getFieldName(fieldIndex, Type.OBJECT)) || fieldType.isPrimitive() : key + " primitive keys must store to J*-fields";
+
+ loadTuple(method, tuple);
+
+ method.putField(fieldClass, fieldName, fieldDesc);
}
/**
@@ -178,16 +184,16 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
*
* @param method Script method.
* @param index Slot index.
- * @param value Value to store.
+ * @param tuple Tuple to store.
*/
- private void putSlot(final MethodEmitter method, final long index, final T value) {
+ private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) {
method.dup();
if (JSType.isRepresentableAsInt(index)) {
- method.load((int) index);
+ method.load((int)index);
} else {
method.load(index);
}
- loadValue(value);
+ loadTuple(method, tuple, false); //we don't pack array like objects
method.dynamicSetIndex(callSiteFlags);
}
@@ -220,11 +226,12 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
* Tally the number of fields and parameters.
*/
private void countFields() {
- for (final Symbol symbol : this.symbols) {
+ for (final MapTuple<T> tuple : tuples) {
+ final Symbol symbol = tuple.symbol;
if (symbol != null) {
if (hasArguments() && symbol.isParam()) {
symbol.setFieldIndex(paramCount++);
- } else {
+ } else if (!isValidArrayIndex(getArrayIndex(tuple.key))) {
symbol.setFieldIndex(fieldCount++);
}
}
diff --git a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
deleted file mode 100644
index 15341484..00000000
--- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ExpressionStatement;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.parser.Token;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.DebugLogger;
-
-/**
- * Lower to more primitive operations. After lowering, an AST has symbols and
- * types. Lowering may also add specialized versions of methods to the script if
- * the optimizer is turned on.
- *
- * Any expression that requires temporary storage as part of computation will
- * also be detected here and give a temporary symbol
- *
- * For any op that we process in FinalizeTypes it is an absolute guarantee
- * that scope and slot information is correct. This enables e.g. AccessSpecialization
- * and frame optimizations
- */
-
-final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
-
- private static final DebugLogger LOG = new DebugLogger("finalize");
-
- private final TemporarySymbols temporarySymbols;
-
- FinalizeTypes(final TemporarySymbols temporarySymbols) {
- super(new LexicalContext());
- this.temporarySymbols = temporarySymbols;
- }
-
- @Override
- public Node leaveForNode(final ForNode forNode) {
- if (forNode.isForIn()) {
- return forNode;
- }
-
- final Expression init = forNode.getInit();
- final Expression test = forNode.getTest();
- final Expression modify = forNode.getModify();
-
- assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
-
- return forNode.
- setInit(lc, init == null ? null : discard(init)).
- setModify(lc, modify == null ? null : discard(modify));
- }
-
- @Override
- public Node leaveCOMMALEFT(final BinaryNode binaryNode) {
- assert binaryNode.getSymbol() != null;
- return binaryNode.setRHS(discard(binaryNode.rhs()));
- }
-
- @Override
- public Node leaveCOMMARIGHT(final BinaryNode binaryNode) {
- assert binaryNode.getSymbol() != null;
- return binaryNode.setLHS(discard(binaryNode.lhs()));
- }
-
- @Override
- public boolean enterBlock(final Block block) {
- updateSymbols(block);
- return true;
- }
-
- @Override
- public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
- temporarySymbols.reuse();
- return expressionStatement.setExpression(discard(expressionStatement.getExpression()));
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- if (functionNode.isLazy()) {
- return false;
- }
-
- // If the function doesn't need a callee, we ensure its __callee__ symbol doesn't get a slot. We can't do
- // this earlier, as access to scoped variables, self symbol, etc. in previous phases can all trigger the
- // need for the callee.
- if (!functionNode.needsCallee()) {
- functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
- }
- // Similar reasoning applies to __scope__ symbol: if the function doesn't need either parent scope and none of
- // its blocks create a scope, we ensure it doesn't get a slot, but we can't determine whether it needs a scope
- // earlier than this phase.
- if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
- functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
- }
-
- return true;
- }
-
- @Override
- public Node leaveFunctionNode(final FunctionNode functionNode) {
- return functionNode.setState(lc, CompilationState.FINALIZED);
- }
-
- private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
- if (LOG.isEnabled()) {
- if (!symbol.isScope()) {
- LOG.finest("updateSymbols: ", symbol, " => scope, because all vars in ", functionNode.getName(), " are in scope");
- }
- if (loseSlot && symbol.hasSlot()) {
- LOG.finest("updateSymbols: ", symbol, " => no slot, because all vars in ", functionNode.getName(), " are in scope");
- }
- }
- }
-
- /**
- * Called after a block or function node (subclass of block) is finished. Guarantees
- * that scope and slot information is correct for every symbol
- * @param block block for which to to finalize type info.
- */
- private void updateSymbols(final Block block) {
- if (!block.needsScope()) {
- return; // nothing to do
- }
-
- final FunctionNode functionNode = lc.getFunction(block);
- final boolean allVarsInScope = functionNode.allVarsInScope();
- final boolean isVarArg = functionNode.isVarArg();
-
- for (final Symbol symbol : block.getSymbols()) {
- if (symbol.isInternal() || symbol.isThis() || symbol.isTemp()) {
- continue;
- }
-
- if (symbol.isVar()) {
- if (allVarsInScope || symbol.isScope()) {
- updateSymbolsLog(functionNode, symbol, true);
- Symbol.setSymbolIsScope(lc, symbol);
- symbol.setNeedsSlot(false);
- } else {
- assert symbol.hasSlot() : symbol + " should have a slot only, no scope";
- }
- } else if (symbol.isParam() && (allVarsInScope || isVarArg || symbol.isScope())) {
- updateSymbolsLog(functionNode, symbol, isVarArg);
- Symbol.setSymbolIsScope(lc, symbol);
- symbol.setNeedsSlot(!isVarArg);
- }
- }
- }
-
- private static Expression discard(final Expression node) {
- if (node.getSymbol() != null) {
- final UnaryNode discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node);
- //discard never has a symbol in the discard node - then it would be a nop
- assert !node.isTerminal();
- return discard;
- }
-
- // node has no result (symbol) so we can keep it the way it is
- return node;
- }
-
-
-}
diff --git a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
new file mode 100644
index 00000000..431244dc
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Establishes depth of scope for non local symbols at the start of method.
+ * If this is a recompilation, the previous data from eager compilation is
+ * stored in the RecompilableScriptFunctionData and is transferred to the
+ * FunctionNode being compiled
+ */
+@Logger(name="scopedepths")
+final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
+
+ private final Compiler compiler;
+ private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
+ private final Map<Integer, Map<String, Integer>> externalSymbolDepths = new HashMap<>();
+ private final Map<Integer, Set<String>> internalSymbols = new HashMap<>();
+ private final Set<Block> withBodies = new HashSet<>();
+
+ private final DebugLogger log;
+
+ private int dynamicScopeCount;
+
+ FindScopeDepths(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ this.log = initLogger(compiler.getContext());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ static int findScopesToStart(final LexicalContext lc, final FunctionNode fn, final Block block) {
+ final Block bodyBlock = findBodyBlock(lc, fn, block);
+ final Iterator<Block> iter = lc.getBlocks(block);
+ Block b = iter.next();
+ int scopesToStart = 0;
+ while (true) {
+ if (b.needsScope()) {
+ scopesToStart++;
+ }
+ if (b == bodyBlock) {
+ break;
+ }
+ b = iter.next();
+ }
+ return scopesToStart;
+ }
+
+ static int findInternalDepth(final LexicalContext lc, final FunctionNode fn, final Block block, final Symbol symbol) {
+ final Block bodyBlock = findBodyBlock(lc, fn, block);
+ final Iterator<Block> iter = lc.getBlocks(block);
+ Block b = iter.next();
+ int scopesToStart = 0;
+ while (true) {
+ if (definedInBlock(b, symbol)) {
+ return scopesToStart;
+ }
+ if (b.needsScope()) {
+ scopesToStart++;
+ }
+ if (b == bodyBlock) {
+ break; //don't go past body block, but process it
+ }
+ b = iter.next();
+ }
+ return -1;
+ }
+
+ private static boolean definedInBlock(final Block block, final Symbol symbol) {
+ if (symbol.isGlobal()) {
+ if (block.isGlobalScope()) {
+ return true;
+ }
+ //globals cannot be defined anywhere else
+ return false;
+ }
+ return block.getExistingSymbol(symbol.getName()) == symbol;
+ }
+
+ static Block findBodyBlock(final LexicalContext lc, final FunctionNode fn, final Block block) {
+ final Iterator<Block> iter = lc.getBlocks(block);
+ while (iter.hasNext()) {
+ final Block next = iter.next();
+ if (fn.getBody() == next) {
+ return next;
+ }
+ }
+ return null;
+ }
+
+ private static Block findGlobalBlock(final LexicalContext lc, final Block block) {
+ final Iterator<Block> iter = lc.getBlocks(block);
+ Block globalBlock = null;
+ while (iter.hasNext()) {
+ globalBlock = iter.next();
+ }
+ return globalBlock;
+ }
+
+ private static boolean isDynamicScopeBoundary(final FunctionNode fn) {
+ return fn.needsDynamicScope();
+ }
+
+ private boolean isDynamicScopeBoundary(final Block block) {
+ return withBodies.contains(block);
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ if (compiler.isOnDemandCompilation()) {
+ return true;
+ }
+
+ if (isDynamicScopeBoundary(functionNode)) {
+ increaseDynamicScopeCount(functionNode);
+ }
+
+ final int fnId = functionNode.getId();
+ Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.get(fnId);
+ if (nestedFunctions == null) {
+ nestedFunctions = new HashMap<>();
+ fnIdToNestedFunctions.put(fnId, nestedFunctions);
+ }
+
+ return true;
+ }
+
+ //external symbols hold the scope depth of sc11 from global at the start of the method
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ final String name = functionNode.getName();
+ FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.SCOPE_DEPTHS_COMPUTED);
+
+ if (compiler.isOnDemandCompilation()) {
+ final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
+ if (data.inDynamicContext()) {
+ log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
+ newFunctionNode = newFunctionNode.setInDynamicContext(lc);
+ }
+ return newFunctionNode;
+ }
+
+ if (inDynamicScope()) {
+ log.fine("Tagging ", quote(name), " as defined in dynamic scope");
+ newFunctionNode = newFunctionNode.setInDynamicContext(lc);
+ }
+
+ //create recompilable scriptfunctiondata
+ final int fnId = newFunctionNode.getId();
+ final Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.remove(fnId);
+
+ assert nestedFunctions != null;
+ // Generate the object class and property map in case this function is ever used as constructor
+ final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
+ newFunctionNode,
+ compiler.getCodeInstaller(),
+ new AllocatorDescriptor(newFunctionNode.getThisProperties()),
+ nestedFunctions,
+ externalSymbolDepths.get(fnId),
+ internalSymbols.get(fnId),
+ compiler.removeSerializedAst(fnId));
+
+ if (lc.getOutermostFunction() != newFunctionNode) {
+ final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
+ if (parentFn != null) {
+ fnIdToNestedFunctions.get(parentFn.getId()).put(fnId, data);
+ }
+ } else {
+ compiler.setData(data);
+ }
+
+ if (isDynamicScopeBoundary(functionNode)) {
+ decreaseDynamicScopeCount(functionNode);
+ }
+
+ return newFunctionNode;
+ }
+
+ private boolean inDynamicScope() {
+ return dynamicScopeCount > 0;
+ }
+
+ private void increaseDynamicScopeCount(final Node node) {
+ assert dynamicScopeCount >= 0;
+ ++dynamicScopeCount;
+ if (log.isEnabled()) {
+ log.finest(quote(lc.getCurrentFunction().getName()), " ++dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
+ }
+ }
+
+ private void decreaseDynamicScopeCount(final Node node) {
+ --dynamicScopeCount;
+ assert dynamicScopeCount >= 0;
+ if (log.isEnabled()) {
+ log.finest(quote(lc.getCurrentFunction().getName()), " --dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
+ }
+ }
+
+ @Override
+ public boolean enterWithNode(final WithNode node) {
+ withBodies.add(node.getBody());
+ return true;
+ }
+
+ @Override
+ public boolean enterBlock(final Block block) {
+ if (compiler.isOnDemandCompilation()) {
+ return true;
+ }
+
+ if (isDynamicScopeBoundary(block)) {
+ increaseDynamicScopeCount(block);
+ }
+
+ if (!lc.isFunctionBody()) {
+ return true;
+ }
+
+ //the below part only happens on eager compilation when we have the entire hierarchy
+ //block is a function body
+ final FunctionNode fn = lc.getCurrentFunction();
+
+ //get all symbols that are referenced inside this function body
+ final Set<Symbol> symbols = new HashSet<>();
+ block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public final boolean enterDefault(final Node node) {
+ if (!compiler.isOnDemandCompilation()) {
+ if (node instanceof IdentNode) {
+ final Symbol symbol = ((IdentNode)node).getSymbol();
+ if (symbol != null && symbol.isScope()) {
+ //if this is an internal symbol, skip it.
+ symbols.add(symbol);
+ }
+ }
+ }
+ return true;
+ }
+ });
+
+ final Map<String, Integer> internals = new HashMap<>();
+
+ final Block globalBlock = findGlobalBlock(lc, block);
+ final Block bodyBlock = findBodyBlock(lc, fn, block);
+
+ assert globalBlock != null;
+ assert bodyBlock != null;
+
+ for (final Symbol symbol : symbols) {
+ Iterator<Block> iter;
+
+ final int internalDepth = findInternalDepth(lc, fn, block, symbol);
+ final boolean internal = internalDepth >= 0;
+ if (internal) {
+ internals.put(symbol.getName(), internalDepth);
+ }
+
+ // if not internal, we have to continue walking until we reach the top. We
+ // start outside the body and each new scope adds a depth count. When we
+ // find the symbol, we store its depth count
+ if (!internal) {
+ int depthAtStart = 0;
+ //not internal - keep looking.
+ iter = lc.getAncestorBlocks(bodyBlock);
+ while (iter.hasNext()) {
+ final Block b2 = iter.next();
+ if (definedInBlock(b2, symbol)) {
+ addExternalSymbol(fn, symbol, depthAtStart);
+ break;
+ }
+ if (b2.needsScope()) {
+ depthAtStart++;
+ }
+ }
+ }
+ }
+
+ addInternalSymbols(fn, internals.keySet());
+
+ if (log.isEnabled()) {
+ log.info(fn.getName() + " internals=" + internals + " externals=" + externalSymbolDepths.get(fn.getId()));
+ }
+
+ return true;
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ if (compiler.isOnDemandCompilation()) {
+ return block;
+ }
+ if (isDynamicScopeBoundary(block)) {
+ decreaseDynamicScopeCount(block);
+ }
+ return block;
+ }
+
+ private void addInternalSymbols(final FunctionNode functionNode, final Set<String> symbols) {
+ final int fnId = functionNode.getId();
+ assert internalSymbols.get(fnId) == null || internalSymbols.get(fnId).equals(symbols); //e.g. cloned finally block
+ internalSymbols.put(fnId, symbols);
+ }
+
+ private void addExternalSymbol(final FunctionNode functionNode, final Symbol symbol, final int depthAtStart) {
+ final int fnId = functionNode.getId();
+ Map<String, Integer> depths = externalSymbolDepths.get(fnId);
+ if (depths == null) {
+ depths = new HashMap<>();
+ externalSymbolDepths.put(fnId, depths);
+ }
+ depths.put(symbol.getName(), depthAtStart);
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/codegen/FoldConstants.java b/src/jdk/nashorn/internal/codegen/FoldConstants.java
index 59362fa2..092b788f 100644
--- a/src/jdk/nashorn/internal/codegen/FoldConstants.java
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java
@@ -26,12 +26,16 @@
package jdk.nashorn.internal.codegen;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.BlockStatement;
+import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.EmptyNode;
+import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IfNode;
@@ -40,30 +44,46 @@ import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.TernaryNode;
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Simple constant folding pass, executed before IR is starting to be lowered.
*/
-final class FoldConstants extends NodeVisitor<LexicalContext> {
+@Logger(name="fold")
+final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
- private static final DebugLogger LOG = new DebugLogger("fold");
+ private final DebugLogger log;
- FoldConstants() {
+ FoldConstants(final Compiler compiler) {
super(new LexicalContext());
+ this.log = initLogger(compiler.getContext());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
}
@Override
public Node leaveUnaryNode(final UnaryNode unaryNode) {
final LiteralNode<?> literalNode = new UnaryNodeConstantEvaluator(unaryNode).eval();
if (literalNode != null) {
- LOG.info("Unary constant folded ", unaryNode, " to ", literalNode);
+ log.info("Unary constant folded ", unaryNode, " to ", literalNode);
return literalNode;
}
return unaryNode;
@@ -73,18 +93,13 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
public Node leaveBinaryNode(final BinaryNode binaryNode) {
final LiteralNode<?> literalNode = new BinaryNodeConstantEvaluator(binaryNode).eval();
if (literalNode != null) {
- LOG.info("Binary constant folded ", binaryNode, " to ", literalNode);
+ log.info("Binary constant folded ", binaryNode, " to ", literalNode);
return literalNode;
}
return binaryNode;
}
@Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- return !functionNode.isLazy();
- }
-
- @Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
}
@@ -116,11 +131,37 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
public Node leaveTernaryNode(final TernaryNode ternaryNode) {
final Node test = ternaryNode.getTest();
if (test instanceof LiteralNode.PrimitiveLiteralNode) {
- return ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression();
+ return (((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression()).getExpression();
}
return ternaryNode;
}
+ @Override
+ public Node leaveSwitchNode(final SwitchNode switchNode) {
+ return switchNode.setUniqueInteger(lc, isUniqueIntegerSwitchNode(switchNode));
+ }
+
+ private static boolean isUniqueIntegerSwitchNode(final SwitchNode switchNode) {
+ final Set<Integer> alreadySeen = new HashSet<>();
+ for (final CaseNode caseNode : switchNode.getCases()) {
+ final Expression test = caseNode.getTest();
+ if (test != null && !isUniqueIntegerLiteral(test, alreadySeen)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isUniqueIntegerLiteral(final Expression expr, final Set<Integer> alreadySeen) {
+ if (expr instanceof LiteralNode) {
+ final Object value = ((LiteralNode<?>)expr).getValue();
+ if (value instanceof Integer) {
+ return alreadySeen.add((Integer)value);
+ }
+ }
+ return false;
+ }
+
/**
* Helper class to evaluate constant expressions at compile time This is
* also a simplifier used by BinaryNode visits, UnaryNode visits and
@@ -149,7 +190,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
final LexicalContext lc = new LexicalContext();
block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
@Override
- public boolean enterVarNode(VarNode varNode) {
+ public boolean enterVarNode(final VarNode varNode) {
statements.add(varNode.setInit(null));
return false;
}
@@ -163,7 +204,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
@Override
protected LiteralNode<?> eval() {
- final Node rhsNode = parent.rhs();
+ final Node rhsNode = parent.getExpression();
if (!(rhsNode instanceof LiteralNode)) {
return null;
@@ -174,7 +215,8 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
}
final LiteralNode<?> rhs = (LiteralNode<?>)rhsNode;
- final boolean rhsInteger = rhs.getType().isInteger();
+ final Type rhsType = rhs.getType();
+ final boolean rhsInteger = rhsType.isInteger() || rhsType.isBoolean();
LiteralNode<?> literalNode;
@@ -261,7 +303,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
break;
case ADD:
if ((lhs.isString() || rhs.isNumeric()) && (rhs.isString() || rhs.isNumeric())) {
- Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
+ final Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
if (res instanceof Number) {
value = ((Number)res).doubleValue();
break;
@@ -280,7 +322,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
value = lhs.getNumber() - rhs.getNumber();
break;
case SHR:
- return LiteralNode.newInstance(token, finish, (lhs.getInt32() >>> rhs.getInt32()) & JSType.MAX_UINT);
+ return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()));
case SAR:
return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
case SHL:
@@ -311,8 +353,8 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
return null;
}
- isInteger &= value != 0.0 && JSType.isRepresentableAsInt(value);
- isLong &= value != 0.0 && JSType.isRepresentableAsLong(value);
+ isInteger &= JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value);
+ isLong &= JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value);
if (isInteger) {
return LiteralNode.newInstance(token, finish, (int)value);
diff --git a/src/jdk/nashorn/internal/codegen/FunctionSignature.java b/src/jdk/nashorn/internal/codegen/FunctionSignature.java
index 1c1b5f74..5e067946 100644
--- a/src/jdk/nashorn/internal/codegen/FunctionSignature.java
+++ b/src/jdk/nashorn/internal/codegen/FunctionSignature.java
@@ -141,7 +141,7 @@ public final class FunctionSignature {
paramTypeList.add(paramType.getTypeClass());
}
- this.methodType = MH.type(returnType.getTypeClass(), paramTypeList.toArray(new Class[paramTypes.length]));
+ this.methodType = MH.type(returnType.getTypeClass(), paramTypeList.toArray(new Class<?>[paramTypes.length]));
}
/**
@@ -195,6 +195,14 @@ public final class FunctionSignature {
}
/**
+ * Get the param types for this function signature
+ * @return cloned vector of param types
+ */
+ public Type[] getParamTypes() {
+ return paramTypes.clone();
+ }
+
+ /**
* Return the {@link MethodType} for this function signature
* @return the method type
*/
diff --git a/src/jdk/nashorn/internal/codegen/Label.java b/src/jdk/nashorn/internal/codegen/Label.java
index 21939dbe..e4b02498 100644
--- a/src/jdk/nashorn/internal/codegen/Label.java
+++ b/src/jdk/nashorn/internal/codegen/Label.java
@@ -24,8 +24,14 @@
*/
package jdk.nashorn.internal.codegen;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.runtime.Debug;
/**
* Abstraction for labels, separating a label from the underlying
@@ -34,24 +40,29 @@ import jdk.nashorn.internal.runtime.Debug;
*
* see -Dnashorn.codegen.debug, --log=codegen
*/
-public final class Label {
+public final class Label implements Serializable {
+ private static final long serialVersionUID = 1L;
+
//byte code generation evaluation type stack for consistency check
//and correct opcode selection. one per label as a label may be a
//join point
- static final class Stack {
- Type[] data = new Type[8];
- int sp = 0;
+ static final class Stack implements Cloneable {
+ static final int NON_LOAD = -1;
- Stack() {
- }
+ Type[] data;
+ int[] localLoads;
+ int sp;
- private Stack(final Type[] type, final int sp) {
- this();
- this.data = new Type[type.length];
- this.sp = sp;
- for (int i = 0; i < sp; i++) {
- data[i] = type[i];
- }
+ List<Type> localVariableTypes;
+ int firstTemp; // index of the first temporary local variable
+ // Bitmap marking last slot belonging to a single symbol.
+ BitSet symbolBoundary;
+
+ Stack() {
+ data = new Type[8];
+ localLoads = new int[8];
+ localVariableTypes = new ArrayList<>(8);
+ symbolBoundary = new BitSet();
}
boolean isEmpty() {
@@ -62,7 +73,147 @@ public final class Label {
return sp;
}
- boolean isEquivalentTo(final Stack other) {
+ void clear() {
+ sp = 0;
+ }
+
+ void push(final Type type) {
+ if (data.length == sp) {
+ final Type[] newData = new Type[sp * 2];
+ final int[] newLocalLoad = new int[sp * 2];
+ System.arraycopy(data, 0, newData, 0, sp);
+ System.arraycopy(localLoads, 0, newLocalLoad, 0, sp);
+ data = newData;
+ localLoads = newLocalLoad;
+ }
+ data[sp] = type;
+ localLoads[sp] = NON_LOAD;
+ sp++;
+ }
+
+ Type peek() {
+ return peek(0);
+ }
+
+ Type peek(final int n) {
+ final int pos = sp - 1 - n;
+ return pos < 0 ? null : data[pos];
+ }
+
+ /**
+ * Retrieve the top <tt>count</tt> types on the stack without modifying it.
+ *
+ * @param count number of types to return
+ * @return array of Types
+ */
+ Type[] getTopTypes(final int count) {
+ final Type[] topTypes = new Type[count];
+ System.arraycopy(data, sp - count, topTypes, 0, count);
+ return topTypes;
+ }
+
+ int[] getLocalLoads(final int from, final int to) {
+ final int count = to - from;
+ final int[] topLocalLoads = new int[count];
+ System.arraycopy(localLoads, from, topLocalLoads, 0, count);
+ return topLocalLoads;
+ }
+
+ /**
+ * Returns the number of used local variable slots, including all live stack-store temporaries.
+ * @return the number of used local variable slots, including all live stack-store temporaries.
+ */
+ int getUsedSlotsWithLiveTemporaries() {
+ // There are at least as many as are declared by the current blocks.
+ int usedSlots = firstTemp;
+ // Look at every load on the stack, and bump the number of used slots up by the temporaries seen there.
+ for(int i = sp; i-->0;) {
+ final int slot = localLoads[i];
+ if(slot != Label.Stack.NON_LOAD) {
+ final int afterSlot = slot + localVariableTypes.get(slot).getSlots();
+ if(afterSlot > usedSlots) {
+ usedSlots = afterSlot;
+ }
+ }
+ }
+ return usedSlots;
+ }
+
+ /**
+ *
+ * @param joinOrigin the stack from the other branch.
+ */
+ void joinFrom(final Stack joinOrigin, final boolean breakTarget) {
+ assert isStackCompatible(joinOrigin);
+ if(breakTarget) {
+ // As we're joining labels that can jump across block boundaries, the number of local variables can
+ // differ, and we should always respect the one having less variables.
+ firstTemp = Math.min(firstTemp, joinOrigin.firstTemp);
+ } else {
+ assert firstTemp == joinOrigin.firstTemp;
+ }
+ final int[] otherLoads = joinOrigin.localLoads;
+ int firstDeadTemp = firstTemp;
+ for(int i = 0; i < sp; ++i) {
+ final int localLoad = localLoads[i];
+ if(localLoad != otherLoads[i]) {
+ localLoads[i] = NON_LOAD;
+ } else if(localLoad >= firstDeadTemp) {
+ firstDeadTemp = localLoad + localVariableTypes.get(localLoad).getSlots();
+ }
+ }
+ // Eliminate dead temporaries
+ undefineLocalVariables(firstDeadTemp, false);
+ assert isVariablePartitioningEqual(joinOrigin, firstDeadTemp);
+ mergeVariableTypes(joinOrigin, firstDeadTemp);
+ }
+
+ private void mergeVariableTypes(final Stack joinOrigin, final int toSlot) {
+ final ListIterator<Type> it1 = localVariableTypes.listIterator();
+ final Iterator<Type> it2 = joinOrigin.localVariableTypes.iterator();
+
+ for(int i = 0; i < toSlot; ++i) {
+ final Type thisType = it1.next();
+ final Type otherType = it2.next();
+ if(otherType == Type.UNKNOWN) {
+ // Variables that are <unknown> on the other branch will become <unknown> here too.
+ it1.set(Type.UNKNOWN);
+ } else if (thisType != otherType) {
+ if(thisType.isObject() && otherType.isObject()) {
+ // different object types are merged into Object.
+ // TODO: maybe find most common superclass?
+ it1.set(Type.OBJECT);
+ } else {
+ assert thisType == Type.UNKNOWN;
+ }
+ }
+ }
+ }
+
+ void joinFromTry(final Stack joinOrigin) {
+ // As we're joining labels that can jump across block boundaries, the number of local variables can
+ // differ, and we should always respect the one having less variables.
+ firstTemp = Math.min(firstTemp, joinOrigin.firstTemp);
+ assert isVariablePartitioningEqual(joinOrigin, firstTemp);
+ mergeVariableTypes(joinOrigin, firstTemp);
+ }
+
+ private int getFirstDeadLocal(final List<Type> types) {
+ int i = types.size();
+ for(final ListIterator<Type> it = types.listIterator(i);
+ it.hasPrevious() && it.previous() == Type.UNKNOWN;
+ --i) {
+ // no body
+ }
+
+ // Respect symbol boundaries; we never chop off half a symbol's storage
+ while(!symbolBoundary.get(i - 1)) {
+ ++i;
+ }
+ return i;
+ }
+
+ private boolean isStackCompatible(final Stack other) {
if (sp != other.sp) {
return false;
}
@@ -74,60 +225,288 @@ public final class Label {
return true;
}
- void clear() {
- sp = 0;
+ private boolean isVariablePartitioningEqual(final Stack other, final int toSlot) {
+ // No difference in the symbol boundaries before the toSlot
+ final BitSet diff = other.getSymbolBoundaryCopy();
+ diff.xor(symbolBoundary);
+ return diff.previousSetBit(toSlot - 1) == -1;
}
- void push(final Type type) {
- if (data.length == sp) {
- final Type[] newData = new Type[sp * 2];
- for (int i = 0; i < sp; i++) {
- newData[i] = data[i];
- }
- data = newData;
+ void markDeadLocalVariables(final int fromSlot, final int slotCount) {
+ final int localCount = localVariableTypes.size();
+ if(fromSlot >= localCount) {
+ return;
+ }
+ final int toSlot = Math.min(fromSlot + slotCount, localCount);
+ invalidateLocalLoadsOnStack(fromSlot, toSlot);
+ for(int i = fromSlot; i < toSlot; ++i) {
+ localVariableTypes.set(i, Type.UNKNOWN);
}
- data[sp++] = type;
}
- Type peek() {
- return peek(0);
+ @SuppressWarnings("unchecked")
+ List<Type> getLocalVariableTypesCopy() {
+ return (List<Type>)((ArrayList<Type>)localVariableTypes).clone();
}
- Type peek(final int n) {
- int pos = sp - 1 - n;
- return pos < 0 ? null : data[pos];
+ BitSet getSymbolBoundaryCopy() {
+ return (BitSet)symbolBoundary.clone();
+ }
+
+ /**
+ * Returns a list of local variable slot types, but for those symbols that have multiple values, only the slot
+ * holding the widest type is marked as live.
+ * @return a list of widest local variable slot types.
+ */
+ List<Type> getWidestLiveLocals(final List<Type> lvarTypes) {
+ final List<Type> widestLiveLocals = new ArrayList<>(lvarTypes);
+ boolean keepNextValue = true;
+ final int size = widestLiveLocals.size();
+ for(int i = size - 1; i-- > 0;) {
+ if(symbolBoundary.get(i)) {
+ keepNextValue = true;
+ }
+ final Type t = widestLiveLocals.get(i);
+ if(t != Type.UNKNOWN) {
+ if(keepNextValue) {
+ if(t != Type.SLOT_2) {
+ keepNextValue = false;
+ }
+ } else {
+ widestLiveLocals.set(i, Type.UNKNOWN);
+ }
+ }
+ }
+ widestLiveLocals.subList(Math.max(getFirstDeadLocal(widestLiveLocals), firstTemp), widestLiveLocals.size()).clear();
+ return widestLiveLocals;
+ }
+
+ String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) {
+ final char[] chars = lvarDescriptor.toCharArray();
+ int j = 0;
+ for(int i = 0; i < chars.length; ++i) {
+ final char c = chars[i];
+ final int nextj = j + CodeGeneratorLexicalContext.getTypeForSlotDescriptor(c).getSlots();
+ if(!symbolBoundary.get(nextj - 1)) {
+ chars[i] = Character.toLowerCase(c);
+ }
+ j = nextj;
+ }
+ return new String(chars);
}
Type pop() {
+ assert sp > 0;
return data[--sp];
}
- Stack copy() {
- return new Stack(data, sp);
+ @Override
+ public Stack clone() {
+ try {
+ final Stack clone = (Stack)super.clone();
+ clone.data = data.clone();
+ clone.localLoads = localLoads.clone();
+ clone.symbolBoundary = getSymbolBoundaryCopy();
+ clone.localVariableTypes = getLocalVariableTypesCopy();
+ return clone;
+ } catch(final CloneNotSupportedException e) {
+ throw new AssertionError("", e);
+ }
}
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder("[");
- for (int i = 0; i < sp; i++) {
- builder.append(data[i]);
- if (i < sp - 1) {
- builder.append(", ");
+ private Stack cloneWithEmptyStack() {
+ final Stack stack = clone();
+ stack.sp = 0;
+ return stack;
+ }
+
+ int getTopLocalLoad() {
+ return localLoads[sp - 1];
+ }
+
+ void markLocalLoad(final int slot) {
+ localLoads[sp - 1] = slot;
+ }
+
+ /**
+ * Performs various bookeeping when a value is stored in a local variable slot.
+ * @param slot the slot written to
+ * @param onlySymbolLiveValue if true, this is the symbol's only live value, and other values of the symbol
+ * should be marked dead
+ * @param Type the type written to the slot
+ */
+ void onLocalStore(final Type type, final int slot, final boolean onlySymbolLiveValue) {
+ if(onlySymbolLiveValue) {
+ final int fromSlot = slot == 0 ? 0 : (symbolBoundary.previousSetBit(slot - 1) + 1);
+ final int toSlot = symbolBoundary.nextSetBit(slot) + 1;
+ for(int i = fromSlot; i < toSlot; ++i) {
+ localVariableTypes.set(i, Type.UNKNOWN);
+ }
+ invalidateLocalLoadsOnStack(fromSlot, toSlot);
+ } else {
+ invalidateLocalLoadsOnStack(slot, slot + type.getSlots());
+ }
+
+ localVariableTypes.set(slot, type);
+ if(type.isCategory2()) {
+ localVariableTypes.set(slot + 1, Type.SLOT_2);
+ }
+ }
+
+ /**
+ * Given a slot range, invalidate knowledge about local loads on stack from these slots (because they're being
+ * killed).
+ * @param fromSlot first slot, inclusive.
+ * @param toSlot last slot, exclusive.
+ */
+ private void invalidateLocalLoadsOnStack(final int fromSlot, final int toSlot) {
+ for(int i = 0; i < sp; ++i) {
+ final int localLoad = localLoads[i];
+ if(localLoad >= fromSlot && localLoad < toSlot) {
+ localLoads[i] = NON_LOAD;
}
}
- return builder.append("]").toString();
+ }
+
+ /**
+ * Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value
+ * in them.
+ * @param fromSlot first slot, inclusive.
+ * @param toSlot last slot, exclusive.
+ */
+ void defineBlockLocalVariable(final int fromSlot, final int toSlot) {
+ defineLocalVariable(fromSlot, toSlot);
+ assert firstTemp < toSlot;
+ firstTemp = toSlot;
+ }
+
+ /**
+ * Defines a new temporary local variable and returns its allocated index.
+ * @param width the required width (in slots) for the new variable.
+ * @return the bytecode slot index where the newly allocated local begins.
+ */
+ int defineTemporaryLocalVariable(final int width) {
+ final int fromSlot = getUsedSlotsWithLiveTemporaries();
+ defineLocalVariable(fromSlot, fromSlot + width);
+ return fromSlot;
+ }
+
+ /**
+ * Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no
+ * live value in them.
+ * @param fromSlot first slot, inclusive.
+ * @param toSlot last slot, exclusive.
+ */
+ void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) {
+ defineLocalVariable(fromSlot, toSlot);
+ }
+
+ private void defineLocalVariable(final int fromSlot, final int toSlot) {
+ assert !hasLoadsOnStack(fromSlot, toSlot);
+ assert fromSlot < toSlot;
+ symbolBoundary.clear(fromSlot, toSlot - 1);
+ symbolBoundary.set(toSlot - 1);
+ final int lastExisting = Math.min(toSlot, localVariableTypes.size());
+ for(int i = fromSlot; i < lastExisting; ++i) {
+ localVariableTypes.set(i, Type.UNKNOWN);
+ }
+ for(int i = lastExisting; i < toSlot; ++i) {
+ localVariableTypes.add(i, Type.UNKNOWN);
+ }
+ }
+
+ /**
+ * Undefines all local variables past the specified slot.
+ * @param fromSlot the first slot to be undefined
+ * @param canTruncateSymbol if false, the fromSlot must be either the first slot of a symbol, or the first slot
+ * after the last symbol. If true, the fromSlot can be in the middle of the storage area for a symbol. This
+ * should be used with care - it is only meant for use in optimism exception handlers.
+ */
+ void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) {
+ final int lvarCount = localVariableTypes.size();
+ assert lvarCount == symbolBoundary.length();
+ assert !hasLoadsOnStack(fromSlot, lvarCount);
+ if(canTruncateSymbol) {
+ if(fromSlot > 0) {
+ symbolBoundary.set(fromSlot - 1);
+ }
+ } else {
+ assert fromSlot == 0 || symbolBoundary.get(fromSlot - 1);
+ }
+ if(fromSlot < lvarCount) {
+ symbolBoundary.clear(fromSlot, lvarCount);
+ localVariableTypes.subList(fromSlot, lvarCount).clear();
+ }
+ firstTemp = Math.min(fromSlot, firstTemp);
+ assert symbolBoundary.length() == localVariableTypes.size();
+ assert symbolBoundary.length() == fromSlot;
+ }
+
+ private void markAsOptimisticCatchHandler(final int liveLocalCount) {
+ // Live temporaries that are no longer on stack are undefined
+ undefineLocalVariables(liveLocalCount, true);
+ // Temporaries are promoted
+ firstTemp = liveLocalCount;
+ // No trailing undefineds
+ localVariableTypes.subList(firstTemp, localVariableTypes.size()).clear();
+ assert symbolBoundary.length() == firstTemp;
+ // Generalize all reference types to Object, and promote boolean to int
+ for(final ListIterator<Type> it = localVariableTypes.listIterator(); it.hasNext();) {
+ final Type type = it.next();
+ if(type == Type.BOOLEAN) {
+ it.set(Type.INT);
+ } else if(type.isObject() && type != Type.OBJECT) {
+ it.set(Type.OBJECT);
+ }
+ }
+ }
+
+ /**
+ * Returns true if any loads on the stack come from the specified slot range.
+ * @param fromSlot start of the range (inclusive)
+ * @param toSlot end of the range (exclusive)
+ * @return true if any loads on the stack come from the specified slot range.
+ */
+ boolean hasLoadsOnStack(final int fromSlot, final int toSlot) {
+ for(int i = 0; i < sp; ++i) {
+ final int load = localLoads[i];
+ if(load >= fromSlot && load < toSlot) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "stack=" + Arrays.toString(Arrays.copyOf(data, sp))
+ + ", symbolBoundaries=" + String.valueOf(symbolBoundary)
+ + ", firstTemp=" + firstTemp
+ + ", localTypes=" + String.valueOf(localVariableTypes)
+ ;
}
}
+ /** Next id for debugging purposes, remove if footprint becomes unmanageable */
+ private static int nextId = 0;
+
/** Name of this label */
private final String name;
/** Type stack at this label */
- private Label.Stack stack;
+ private transient Label.Stack stack;
/** ASM representation of this label */
private jdk.internal.org.objectweb.asm.Label label;
+ /** Id for debugging purposes, remove if footprint becomes unmanageable */
+ private final int id;
+
+ /** Is this label reachable (anything ever jumped to it)? */
+ private transient boolean reachable;
+
+ private transient boolean breakTarget;
+
/**
* Constructor
*
@@ -136,6 +515,7 @@ public final class Label {
public Label(final String name) {
super();
this.name = name;
+ this.id = nextId++;
}
/**
@@ -146,9 +526,9 @@ public final class Label {
public Label(final Label label) {
super();
this.name = label.name;
+ this.id = label.id;
}
-
jdk.internal.org.objectweb.asm.Label getLabel() {
if (this.label == null) {
this.label = new jdk.internal.org.objectweb.asm.Label();
@@ -160,12 +540,66 @@ public final class Label {
return stack;
}
- void setStack(final Label.Stack stack) {
- this.stack = stack;
+ void joinFrom(final Label.Stack joinOrigin) {
+ this.reachable = true;
+ if(stack == null) {
+ stack = joinOrigin.clone();
+ } else {
+ stack.joinFrom(joinOrigin, breakTarget);
+ }
}
+ void joinFromTry(final Label.Stack joinOrigin, final boolean isOptimismHandler) {
+ this.reachable = true;
+ if (stack == null) {
+ if(!isOptimismHandler) {
+ stack = joinOrigin.cloneWithEmptyStack();
+ // Optimism handler needs temporaries to remain live, others don't.
+ stack.undefineLocalVariables(stack.firstTemp, false);
+ }
+ } else {
+ assert !isOptimismHandler;
+ stack.joinFromTry(joinOrigin);
+ }
+ }
+
+ void markAsBreakTarget() {
+ breakTarget = true;
+ }
+
+ boolean isBreakTarget() {
+ return breakTarget;
+ }
+
+ void onCatch() {
+ if(stack != null) {
+ stack = stack.cloneWithEmptyStack();
+ }
+ }
+ void markAsOptimisticCatchHandler(final Label.Stack currentStack, final int liveLocalCount) {
+ stack = currentStack.cloneWithEmptyStack();
+ stack.markAsOptimisticCatchHandler(liveLocalCount);
+ }
+
+ void markAsOptimisticContinuationHandlerFor(final Label afterConsumeStackLabel) {
+ stack = afterConsumeStackLabel.stack.cloneWithEmptyStack();
+ }
+
+ boolean isReachable() {
+ return reachable;
+ }
+
+ boolean isAfter(final Label other) {
+ return label.getOffset() > other.label.getOffset();
+ }
+
+ private String str;
+
@Override
public String toString() {
- return name + '_' + Debug.id(this);
+ if (str == null) {
+ str = name + '_' + id;
+ }
+ return str;
}
}
diff --git a/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java b/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java
new file mode 100644
index 00000000..8ee1e9e5
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.codegen;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Encapsulates the information for restoring the local state when continuing execution after a rewrite triggered by
+ * an optimistic assumption failure. An instance of this class is specific to a program point.
+ *
+ */
+public class LocalStateRestorationInfo {
+ private final Type[] localVariableTypes;
+ private final int[] stackLoads;
+
+ LocalStateRestorationInfo(final Type[] localVariableTypes, final int[] stackLoads) {
+ this.localVariableTypes = localVariableTypes;
+ this.stackLoads = stackLoads;
+ }
+
+ /**
+ * Returns the types of the local variables at the continuation of a program point.
+ * @return the types of the local variables at the continuation of a program point.
+ */
+ public Type[] getLocalVariableTypes() {
+ return localVariableTypes.clone();
+ }
+
+ /**
+ * Returns the indices of local variables that need to be loaded on stack before jumping to the continuation of the
+ * program point.
+ * @return the indices of local variables that need to be loaded on stack.
+ */
+ public int[] getStackLoads() {
+ return stackLoads.clone();
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
new file mode 100644
index 00000000..ac3c2934
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysFalse;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BaseNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BreakNode;
+import jdk.nashorn.internal.ir.BreakableNode;
+import jdk.nashorn.internal.ir.CaseNode;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ContinueNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.PropertyNode;
+import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.SplitReturn;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.ThrowNode;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WhileNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
+
+/**
+ * Calculates types for local variables. For purposes of local variable type calculation, the only types used are
+ * Undefined, boolean, int, long, double, and Object. The calculation eagerly widens types of local variable to their
+ * widest at control flow join points.
+ * TODO: investigate a more sophisticated solution that uses use/def information to only widens the type of a local
+ * variable to its widest used type after the join point. That would eliminate some widenings of undefined variables to
+ * object, most notably those used only in loops. We need a full liveness analysis for that. Currently, we can establish
+ * per-type liveness, which eliminates most of unwanted dead widenings.
+ * NOTE: the way this class is implemented, it actually processes the AST in two passes. The first pass is top-down and
+ * implemented in {@code enterXxx} methods. This pass does not mutate the AST (except for one occurrence, noted below),
+ * as being able to find relevant labels for control flow joins is sensitive to their reference identity, and mutated
+ * label-carrying nodes will create copies of their labels. A second bottom-up pass applying the changes is implemented
+ * in the separate visitor sitting in {@link #leaveFunctionNode(FunctionNode)}. This visitor will also instantiate new
+ * instances of the calculator to be run on nested functions (when not lazy compiling).
+ *
+ */
+final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
+
+ private static class JumpOrigin {
+ final JoinPredecessor node;
+ final Map<Symbol, LvarType> types;
+
+ JumpOrigin(final JoinPredecessor node, final Map<Symbol, LvarType> types) {
+ this.node = node;
+ this.types = types;
+ }
+ }
+
+ private static class JumpTarget {
+ private final List<JumpOrigin> origins = new LinkedList<>();
+ private Map<Symbol, LvarType> types = Collections.emptyMap();
+
+ void addOrigin(final JoinPredecessor originNode, final Map<Symbol, LvarType> originTypes) {
+ origins.add(new JumpOrigin(originNode, originTypes));
+ this.types = getUnionTypes(this.types, originTypes);
+ }
+ }
+ private enum LvarType {
+ UNDEFINED(Type.UNDEFINED),
+ BOOLEAN(Type.BOOLEAN),
+ INT(Type.INT),
+ LONG(Type.LONG),
+ DOUBLE(Type.NUMBER),
+ OBJECT(Type.OBJECT);
+
+ private final Type type;
+ private LvarType(final Type type) {
+ this.type = type;
+ }
+ }
+
+ private static final Map<Type, LvarType> TO_LVAR_TYPE = new IdentityHashMap<>();
+
+ static {
+ for(final LvarType lvarType: LvarType.values()) {
+ TO_LVAR_TYPE.put(lvarType.type, lvarType);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static IdentityHashMap<Symbol, LvarType> cloneMap(final Map<Symbol, LvarType> map) {
+ return (IdentityHashMap<Symbol, LvarType>)((IdentityHashMap<?,?>)map).clone();
+ }
+
+ private LocalVariableConversion createConversion(final Symbol symbol, final LvarType branchLvarType,
+ final Map<Symbol, LvarType> joinLvarTypes, final LocalVariableConversion next) {
+ final LvarType targetType = joinLvarTypes.get(symbol);
+ assert targetType != null;
+ if(targetType == branchLvarType) {
+ return next;
+ }
+ // NOTE: we could naively just use symbolIsUsed(symbol, branchLvarType) here, but that'd be wrong. While
+ // technically a conversion will read the value of the symbol with that type, but it will also write it to a new
+ // type, and that type might be dead (we can't know yet). For this reason, we don't treat conversion reads as
+ // real uses until we know their target type is live. If we didn't do this, and just did a symbolIsUsed here,
+ // we'd introduce false live variables which could nevertheless turn into dead ones in a subsequent
+ // deoptimization, causing a shift in the list of live locals that'd cause erroneous restoration of
+ // continuations (since RewriteException's byteCodeSlots carries an array and not a name-value map).
+
+ symbolIsConverted(symbol, branchLvarType, targetType);
+ //symbolIsUsed(symbol, branchLvarType);
+ return new LocalVariableConversion(symbol, branchLvarType.type, targetType.type, next);
+ }
+
+ private static Map<Symbol, LvarType> getUnionTypes(final Map<Symbol, LvarType> types1, final Map<Symbol, LvarType> types2) {
+ if(types1 == types2 || types1.isEmpty()) {
+ return types2;
+ } else if(types2.isEmpty()) {
+ return types1;
+ }
+ final Set<Symbol> commonSymbols = new HashSet<>(types1.keySet());
+ commonSymbols.retainAll(types2.keySet());
+ // We have a chance of returning an unmodified set if both sets have the same keys and one is strictly wider
+ // than the other.
+ final int commonSize = commonSymbols.size();
+ final int types1Size = types1.size();
+ final int types2Size = types2.size();
+ if(commonSize == types1Size && commonSize == types2Size) {
+ boolean matches1 = true, matches2 = true;
+ Map<Symbol, LvarType> union = null;
+ for(final Symbol symbol: commonSymbols) {
+ final LvarType type1 = types1.get(symbol);
+ final LvarType type2 = types2.get(symbol);
+ final LvarType widest = widestLvarType(type1, type2);
+ if(widest != type1 && matches1) {
+ matches1 = false;
+ if(!matches2) {
+ union = cloneMap(types1);
+ }
+ }
+ if (widest != type2 && matches2) {
+ matches2 = false;
+ if(!matches1) {
+ union = cloneMap(types2);
+ }
+ }
+ if(!(matches1 || matches2) && union != null) { //remove overly enthusiastic "union can be null" warning
+ assert union != null;
+ union.put(symbol, widest);
+ }
+ }
+ return matches1 ? types1 : matches2 ? types2 : union;
+ }
+ // General case
+ final Map<Symbol, LvarType> union;
+ if(types1Size > types2Size) {
+ union = cloneMap(types1);
+ union.putAll(types2);
+ } else {
+ union = cloneMap(types2);
+ union.putAll(types1);
+ }
+ for(final Symbol symbol: commonSymbols) {
+ final LvarType type1 = types1.get(symbol);
+ final LvarType type2 = types2.get(symbol);
+ union.put(symbol, widestLvarType(type1, type2));
+ }
+ return union;
+ }
+
+ private static void symbolIsUsed(final Symbol symbol, final LvarType type) {
+ if(type != LvarType.UNDEFINED) {
+ symbol.setHasSlotFor(type.type);
+ }
+ }
+
+ private static class SymbolConversions {
+ private static byte I2L = 1 << 0;
+ private static byte I2D = 1 << 1;
+ private static byte I2O = 1 << 2;
+ private static byte L2D = 1 << 3;
+ private static byte L2O = 1 << 4;
+ private static byte D2O = 1 << 5;
+
+ private byte conversions;
+
+ void recordConversion(final LvarType from, final LvarType to) {
+ switch (from) {
+ case UNDEFINED:
+ return;
+ case INT:
+ case BOOLEAN:
+ switch (to) {
+ case LONG:
+ recordConversion(I2L);
+ return;
+ case DOUBLE:
+ recordConversion(I2D);
+ return;
+ case OBJECT:
+ recordConversion(I2O);
+ return;
+ default:
+ illegalConversion(from, to);
+ return;
+ }
+ case LONG:
+ switch (to) {
+ case DOUBLE:
+ recordConversion(L2D);
+ return;
+ case OBJECT:
+ recordConversion(L2O);
+ return;
+ default:
+ illegalConversion(from, to);
+ return;
+ }
+ case DOUBLE:
+ if(to == LvarType.OBJECT) {
+ recordConversion(D2O);
+ }
+ return;
+ default:
+ illegalConversion(from, to);
+ }
+ }
+
+ private static void illegalConversion(final LvarType from, final LvarType to) {
+ throw new AssertionError("Invalid conversion from " + from + " to " + to);
+ }
+
+ void recordConversion(final byte convFlag) {
+ conversions = (byte)(conversions | convFlag);
+ }
+
+ boolean hasConversion(final byte convFlag) {
+ return (conversions & convFlag) != 0;
+ }
+
+ void calculateTypeLiveness(final Symbol symbol) {
+ if(symbol.hasSlotFor(Type.OBJECT)) {
+ if(hasConversion(D2O)) {
+ symbol.setHasSlotFor(Type.NUMBER);
+ }
+ if(hasConversion(L2O)) {
+ symbol.setHasSlotFor(Type.LONG);
+ }
+ if(hasConversion(I2O)) {
+ symbol.setHasSlotFor(Type.INT);
+ }
+ }
+ if(symbol.hasSlotFor(Type.NUMBER)) {
+ if(hasConversion(L2D)) {
+ symbol.setHasSlotFor(Type.LONG);
+ }
+ if(hasConversion(I2D)) {
+ symbol.setHasSlotFor(Type.INT);
+ }
+ }
+ if(symbol.hasSlotFor(Type.LONG)) {
+ if(hasConversion(I2L)) {
+ symbol.setHasSlotFor(Type.INT);
+ }
+ }
+ }
+ }
+
+ private void symbolIsConverted(final Symbol symbol, final LvarType from, final LvarType to) {
+ SymbolConversions conversions = symbolConversions.get(symbol);
+ if(conversions == null) {
+ conversions = new SymbolConversions();
+ symbolConversions.put(symbol, conversions);
+ }
+ conversions.recordConversion(from, to);
+ }
+
+ private static LvarType toLvarType(final Type type) {
+ assert type != null;
+ final LvarType lvarType = TO_LVAR_TYPE.get(type);
+ if(lvarType != null) {
+ return lvarType;
+ }
+ assert type.isObject();
+ return LvarType.OBJECT;
+ }
+ private static LvarType widestLvarType(final LvarType t1, final LvarType t2) {
+ if(t1 == t2) {
+ return t1;
+ }
+ // Undefined or boolean to anything always widens to object.
+ if(t1.ordinal() < LvarType.INT.ordinal() || t2.ordinal() < LvarType.INT.ordinal()) {
+ return LvarType.OBJECT;
+ }
+ // NOTE: we allow "widening" of long to double even though it can lose precision. ECMAScript doesn't have an
+ // Int64 type anyway, so this loss of precision is actually more conformant to the specification...
+ return LvarType.values()[Math.max(t1.ordinal(), t2.ordinal())];
+ }
+ private final Compiler compiler;
+ private final Map<Label, JumpTarget> jumpTargets = new IdentityHashMap<>();
+ // Local variable type mapping at the currently evaluated point. No map instance is ever modified; setLvarType() always
+ // allocates a new map. Immutability of maps allows for cheap snapshots by just keeping the reference to the current
+ // value.
+ private Map<Symbol, LvarType> localVariableTypes = new IdentityHashMap<>();
+
+ // Whether the current point in the AST is reachable code
+ private boolean reachable = true;
+ // Return type of the function
+ private Type returnType = Type.UNKNOWN;
+ // Synthetic return node that we must insert at the end of the function if it's end is reachable.
+ private ReturnNode syntheticReturn;
+
+ private boolean alreadyEnteredTopLevelFunction;
+
+ // LvarType and conversion information gathered during the top-down pass; applied to nodes in the bottom-up pass.
+ private final Map<JoinPredecessor, LocalVariableConversion> localVariableConversions = new IdentityHashMap<>();
+
+ private final Map<IdentNode, LvarType> identifierLvarTypes = new IdentityHashMap<>();
+ private final Map<Symbol, SymbolConversions> symbolConversions = new IdentityHashMap<>();
+
+ private SymbolToType symbolToType = new SymbolToType();
+
+ // Stack of open labels for starts of catch blocks, one for every currently traversed try block; for inserting
+ // control flow edges to them. Note that we currently don't insert actual control flow edges, but instead edges that
+ // help us with type calculations. This means that some operations that can result in an exception being thrown
+ // aren't considered (function calls, side effecting property getters and setters etc.), while some operations that
+ // don't result in control flow transfers do originate an edge to the catch blocks (namely, assignments to local
+ // variables).
+ private final Deque<Label> catchLabels = new ArrayDeque<>();
+
+ LocalVariableTypesCalculator(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ }
+
+ private JumpTarget createJumpTarget(final Label label) {
+ assert !jumpTargets.containsKey(label);
+ final JumpTarget jumpTarget = new JumpTarget();
+ jumpTargets.put(label, jumpTarget);
+ return jumpTarget;
+ }
+
+ private void doesNotContinueSequentially() {
+ reachable = false;
+ localVariableTypes = Collections.emptyMap();
+ }
+
+
+ @Override
+ public boolean enterBinaryNode(final BinaryNode binaryNode) {
+ // NOTE: regardless of operator's lexical associativity, lhs is always evaluated first.
+ final Expression lhs = binaryNode.lhs();
+ final boolean isAssignment = binaryNode.isAssignment();
+ LvarType lhsTypeOnLoad = null;
+ if(isAssignment) {
+ if(lhs instanceof BaseNode) {
+ ((BaseNode)lhs).getBase().accept(this);
+ if(lhs instanceof IndexNode) {
+ ((IndexNode)lhs).getIndex().accept(this);
+ } else {
+ assert lhs instanceof AccessNode;
+ }
+ } else {
+ assert lhs instanceof IdentNode;
+ if(binaryNode.isSelfModifying()) {
+ final IdentNode ident = ((IdentNode)lhs);
+ ident.accept(this);
+ // Self-assignment can cause a change in the type of the variable. For purposes of evaluating
+ // the type of the operation, we must use its type as it was when it was loaded. If we didn't
+ // do this, some awkward expressions would end up being calculated incorrectly, e.g.
+ // "var x; x += x = 0;". In this case we have undefined+int so the result type is double (NaN).
+ // However, if we used the type of "x" on LHS after we evaluated RHS, we'd see int+int, so the
+ // result type would be either optimistic int or pessimistic long, which would be wrong.
+ lhsTypeOnLoad = getLocalVariableTypeIfBytecode(ident.getSymbol());
+ }
+ }
+ } else {
+ lhs.accept(this);
+ }
+
+ final boolean isLogical = binaryNode.isLogical();
+ assert !(isAssignment && isLogical); // there are no logical assignment operators in JS
+ final Label joinLabel = isLogical ? new Label("") : null;
+ if(isLogical) {
+ jumpToLabel((JoinPredecessor)lhs, joinLabel);
+ }
+
+ final Expression rhs = binaryNode.rhs();
+ rhs.accept(this);
+ if(isLogical) {
+ jumpToLabel((JoinPredecessor)rhs, joinLabel);
+ }
+ joinOnLabel(joinLabel);
+
+ if(isAssignment && lhs instanceof IdentNode) {
+ if(binaryNode.isSelfModifying()) {
+ onSelfAssignment((IdentNode)lhs, binaryNode, lhsTypeOnLoad);
+ } else {
+ onAssignment((IdentNode)lhs, rhs);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterBlock(final Block block) {
+ for(final Symbol symbol: block.getSymbols()) {
+ if(symbol.isBytecodeLocal() && getLocalVariableTypeOrNull(symbol) == null) {
+ setType(symbol, LvarType.UNDEFINED);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean enterBreakNode(final BreakNode breakNode) {
+ return enterJumpStatement(breakNode);
+ }
+
+ @Override
+ public boolean enterContinueNode(final ContinueNode continueNode) {
+ return enterJumpStatement(continueNode);
+ }
+
+ private boolean enterJumpStatement(final JumpStatement jump) {
+ if(!reachable) {
+ return false;
+ }
+ final BreakableNode target = jump.getTarget(lc);
+ jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target));
+ doesNotContinueSequentially();
+ return false;
+ }
+
+ @Override
+ protected boolean enterDefault(final Node node) {
+ return reachable;
+ }
+
+ private void enterDoWhileLoop(final WhileNode loopNode) {
+ final JoinPredecessorExpression test = loopNode.getTest();
+ final Block body = loopNode.getBody();
+ final Label continueLabel = loopNode.getContinueLabel();
+ final Label breakLabel = loopNode.getBreakLabel();
+ final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes;
+ final Label repeatLabel = new Label("");
+ for(;;) {
+ jumpToLabel(loopNode, repeatLabel, beforeLoopTypes);
+ final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes;
+ body.accept(this);
+ if(reachable) {
+ jumpToLabel(body, continueLabel);
+ }
+ joinOnLabel(continueLabel);
+ if(!reachable) {
+ break;
+ }
+ test.accept(this);
+ jumpToLabel(test, breakLabel);
+ if(isAlwaysFalse(test)) {
+ break;
+ }
+ jumpToLabel(test, repeatLabel);
+ joinOnLabel(repeatLabel);
+ if(localVariableTypes.equals(beforeRepeatTypes)) {
+ break;
+ }
+ resetJoinPoint(continueLabel);
+ resetJoinPoint(breakLabel);
+ resetJoinPoint(repeatLabel);
+ }
+
+ if(isAlwaysTrue(test)) {
+ doesNotContinueSequentially();
+ }
+
+ leaveBreakable(loopNode);
+ }
+
+ @Override
+ public boolean enterForNode(final ForNode forNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ final Expression init = forNode.getInit();
+ if(forNode.isForIn()) {
+ final JoinPredecessorExpression iterable = forNode.getModify();
+ iterable.accept(this);
+ enterTestFirstLoop(forNode, null, init,
+ // If we're iterating over property names, and we can discern from the runtime environment
+ // of the compilation that the object being iterated over must use strings for property
+ // names (e.g., it is a native JS object or array), then we'll not bother trying to treat
+ // the property names optimistically.
+ !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression())));
+ } else {
+ if(init != null) {
+ init.accept(this);
+ }
+ enterTestFirstLoop(forNode, forNode.getModify(), null, false);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ if(alreadyEnteredTopLevelFunction) {
+ return false;
+ }
+ int pos = 0;
+ if(!functionNode.isVarArg()) {
+ for (final IdentNode param : functionNode.getParameters()) {
+ final Symbol symbol = param.getSymbol();
+ // Parameter is not necessarily bytecode local as it can be scoped due to nested context use, but it
+ // must have a slot if we aren't in a function with vararg signature.
+ assert symbol.hasSlot();
+ final Type callSiteParamType = compiler.getParamType(functionNode, pos);
+ final LvarType paramType = callSiteParamType == null ? LvarType.OBJECT : toLvarType(callSiteParamType);
+ setType(symbol, paramType);
+ // Make sure parameter slot for its incoming value is not marked dead. NOTE: this is a heuristic. Right
+ // now, CodeGenerator.expandParameters() relies on the fact that every parameter's final slot width will
+ // be at least the same as incoming width, therefore even if a parameter is never read, we'll still keep
+ // its slot.
+ symbolIsUsed(symbol);
+ setIdentifierLvarType(param, paramType);
+ pos++;
+ }
+ }
+ setCompilerConstantAsObject(functionNode, CompilerConstants.THIS);
+
+ // TODO: coarse-grained. If we wanted to solve it completely precisely,
+ // we'd also need to push/pop its type when handling WithNode (so that
+ // it can go back to undefined after a 'with' block.
+ if(functionNode.hasScopeBlock() || functionNode.needsParentScope()) {
+ setCompilerConstantAsObject(functionNode, CompilerConstants.SCOPE);
+ }
+ if(functionNode.needsCallee()) {
+ setCompilerConstantAsObject(functionNode, CompilerConstants.CALLEE);
+ }
+ if(functionNode.needsArguments()) {
+ setCompilerConstantAsObject(functionNode, CompilerConstants.ARGUMENTS);
+ }
+
+ alreadyEnteredTopLevelFunction = true;
+ return true;
+ }
+
+ @Override
+ public boolean enterIdentNode(final IdentNode identNode) {
+ final Symbol symbol = identNode.getSymbol();
+ if(symbol.isBytecodeLocal()) {
+ symbolIsUsed(symbol);
+ setIdentifierLvarType(identNode, getLocalVariableType(symbol));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterIfNode(final IfNode ifNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ final Expression test = ifNode.getTest();
+ final Block pass = ifNode.getPass();
+ final Block fail = ifNode.getFail();
+
+ test.accept(this);
+
+ final Map<Symbol, LvarType> afterTestLvarTypes = localVariableTypes;
+ if(!isAlwaysFalse(test)) {
+ pass.accept(this);
+ }
+ final Map<Symbol, LvarType> passLvarTypes = localVariableTypes;
+ final boolean reachableFromPass = reachable;
+
+ reachable = true;
+ localVariableTypes = afterTestLvarTypes;
+ if(!isAlwaysTrue(test) && fail != null) {
+ fail.accept(this);
+ final boolean reachableFromFail = reachable;
+ reachable |= reachableFromPass;
+ if(!reachable) {
+ return false;
+ }
+
+ if(reachableFromFail) {
+ if(reachableFromPass) {
+ final Map<Symbol, LvarType> failLvarTypes = localVariableTypes;
+ localVariableTypes = getUnionTypes(passLvarTypes, failLvarTypes);
+ setConversion(pass, passLvarTypes, localVariableTypes);
+ setConversion(fail, failLvarTypes, localVariableTypes);
+ }
+ return false;
+ }
+ }
+
+ if(reachableFromPass) {
+ localVariableTypes = getUnionTypes(afterTestLvarTypes, passLvarTypes);
+ // IfNode itself is associated with conversions that might need to be performed after the test if there's no
+ // else branch. E.g.
+ // if(x = 1, cond) { x = 1.0 } must widen "x = 1" to a double.
+ setConversion(pass, passLvarTypes, localVariableTypes);
+ setConversion(ifNode, afterTestLvarTypes, localVariableTypes);
+ } else {
+ localVariableTypes = afterTestLvarTypes;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean enterPropertyNode(final PropertyNode propertyNode) {
+ // Avoid falsely adding property keys to the control flow graph
+ if(propertyNode.getValue() != null) {
+ propertyNode.getValue().accept(this);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterReturnNode(final ReturnNode returnNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ final Expression returnExpr = returnNode.getExpression();
+ final Type returnExprType;
+ if(returnExpr != null) {
+ returnExpr.accept(this);
+ returnExprType = getType(returnExpr);
+ } else {
+ returnExprType = Type.UNDEFINED;
+ }
+ returnType = Type.widestReturnType(returnType, returnExprType);
+ doesNotContinueSequentially();
+ return false;
+ }
+
+ @Override
+ public boolean enterSplitReturn(final SplitReturn splitReturn) {
+ doesNotContinueSequentially();
+ return false;
+ }
+
+ @Override
+ public boolean enterSwitchNode(final SwitchNode switchNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ final Expression expr = switchNode.getExpression();
+ expr.accept(this);
+
+ final List<CaseNode> cases = switchNode.getCases();
+ if(cases.isEmpty()) {
+ return false;
+ }
+
+ // Control flow is different for all-integer cases where we dispatch by switch table, and for all other cases
+ // where we do sequential comparison. Note that CaseNode objects act as join points.
+ final boolean isInteger = switchNode.isUniqueInteger();
+ final Label breakLabel = switchNode.getBreakLabel();
+ final boolean hasDefault = switchNode.getDefaultCase() != null;
+
+ boolean tagUsed = false;
+ for(final CaseNode caseNode: cases) {
+ final Expression test = caseNode.getTest();
+ if(!isInteger && test != null) {
+ test.accept(this);
+ if(!tagUsed) {
+ symbolIsUsed(switchNode.getTag(), LvarType.OBJECT);
+ tagUsed = true;
+ }
+ }
+ // CaseNode carries the conversions that need to be performed on its entry from the test.
+ // CodeGenerator ensures these are only emitted when arriving on the branch and not through a
+ // fallthrough.
+ jumpToLabel(caseNode, caseNode.getBody().getEntryLabel());
+ }
+ if(!hasDefault) {
+ // No default case means we can arrive at the break label without entering any cases. In that case
+ // SwitchNode will carry the conversions that need to be performed before it does that jump.
+ jumpToLabel(switchNode, breakLabel);
+ }
+
+ // All cases are arrived at through jumps
+ doesNotContinueSequentially();
+
+ Block previousBlock = null;
+ for(final CaseNode caseNode: cases) {
+ final Block body = caseNode.getBody();
+ final Label entryLabel = body.getEntryLabel();
+ if(previousBlock != null && reachable) {
+ jumpToLabel(previousBlock, entryLabel);
+ }
+ joinOnLabel(entryLabel);
+ assert reachable == true;
+ body.accept(this);
+ previousBlock = body;
+ }
+ if(previousBlock != null && reachable) {
+ jumpToLabel(previousBlock, breakLabel);
+ }
+ leaveBreakable(switchNode);
+ return false;
+ }
+
+ @Override
+ public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+ final Expression test = ternaryNode.getTest();
+ final Expression trueExpr = ternaryNode.getTrueExpression();
+ final Expression falseExpr = ternaryNode.getFalseExpression();
+
+ test.accept(this);
+
+ final Map<Symbol, LvarType> testExitLvarTypes = localVariableTypes;
+ if(!isAlwaysFalse(test)) {
+ trueExpr.accept(this);
+ }
+ final Map<Symbol, LvarType> trueExitLvarTypes = localVariableTypes;
+ localVariableTypes = testExitLvarTypes;
+ if(!isAlwaysTrue(test)) {
+ falseExpr.accept(this);
+ }
+ final Map<Symbol, LvarType> falseExitLvarTypes = localVariableTypes;
+ localVariableTypes = getUnionTypes(trueExitLvarTypes, falseExitLvarTypes);
+ setConversion((JoinPredecessor)trueExpr, trueExitLvarTypes, localVariableTypes);
+ setConversion((JoinPredecessor)falseExpr, falseExitLvarTypes, localVariableTypes);
+ return false;
+ }
+
+ private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify,
+ final Expression iteratorValues, final boolean iteratorValuesAreObject) {
+ final JoinPredecessorExpression test = loopNode.getTest();
+ if(isAlwaysFalse(test)) {
+ test.accept(this);
+ return;
+ }
+
+ final Label continueLabel = loopNode.getContinueLabel();
+ final Label breakLabel = loopNode.getBreakLabel();
+
+ final Label repeatLabel = modify == null ? continueLabel : new Label("");
+ final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes;
+ for(;;) {
+ jumpToLabel(loopNode, repeatLabel, beforeLoopTypes);
+ final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes;
+ if(test != null) {
+ test.accept(this);
+ }
+ if(!isAlwaysTrue(test)) {
+ jumpToLabel(test, breakLabel);
+ }
+ if(iteratorValues instanceof IdentNode) {
+ final IdentNode ident = (IdentNode)iteratorValues;
+ // Receives iterator values; the optimistic type of the iterator values is tracked on the
+ // identifier, but we override optimism if it's known that the object being iterated over will
+ // never have primitive property names.
+ onAssignment(ident, iteratorValuesAreObject ? LvarType.OBJECT :
+ toLvarType(compiler.getOptimisticType(ident)));
+ }
+ final Block body = loopNode.getBody();
+ body.accept(this);
+ if(reachable) {
+ jumpToLabel(body, continueLabel);
+ }
+ joinOnLabel(continueLabel);
+ if(!reachable) {
+ break;
+ }
+ if(modify != null) {
+ modify.accept(this);
+ jumpToLabel(modify, repeatLabel);
+ joinOnLabel(repeatLabel);
+ }
+ if(localVariableTypes.equals(beforeRepeatTypes)) {
+ break;
+ }
+ // Reset the join points and repeat the analysis
+ resetJoinPoint(continueLabel);
+ resetJoinPoint(breakLabel);
+ resetJoinPoint(repeatLabel);
+ }
+
+ if(isAlwaysTrue(test) && iteratorValues == null) {
+ doesNotContinueSequentially();
+ }
+
+ leaveBreakable(loopNode);
+ }
+
+ @Override
+ public boolean enterThrowNode(final ThrowNode throwNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ throwNode.getExpression().accept(this);
+ jumpToCatchBlock(throwNode);
+ doesNotContinueSequentially();
+ return false;
+ }
+
+ @Override
+ public boolean enterTryNode(final TryNode tryNode) {
+ if(!reachable) {
+ return false;
+ }
+
+ // This is the label for the join point at the entry of the catch blocks.
+ final Label catchLabel = new Label("");
+ catchLabels.push(catchLabel);
+
+ // Presume that even the start of the try block can immediately go to the catch
+ jumpToLabel(tryNode, catchLabel);
+
+ final Block body = tryNode.getBody();
+ body.accept(this);
+ catchLabels.pop();
+
+ // Final exit label for the whole try/catch construct (after the try block and after all catches).
+ final Label endLabel = new Label("");
+
+ boolean canExit = false;
+ if(reachable) {
+ jumpToLabel(body, endLabel);
+ canExit = true;
+ }
+ doesNotContinueSequentially();
+
+ joinOnLabel(catchLabel);
+ for(final CatchNode catchNode: tryNode.getCatches()) {
+ final IdentNode exception = catchNode.getException();
+ onAssignment(exception, LvarType.OBJECT);
+ final Expression condition = catchNode.getExceptionCondition();
+ if(condition != null) {
+ condition.accept(this);
+ }
+ final Map<Symbol, LvarType> afterConditionTypes = localVariableTypes;
+ final Block catchBody = catchNode.getBody();
+ // TODO: currently, we consider that the catch blocks are always reachable from the try block as currently
+ // we lack enough analysis to prove that no statement before a break/continue/return in the try block can
+ // throw an exception.
+ reachable = true;
+ catchBody.accept(this);
+ final Symbol exceptionSymbol = exception.getSymbol();
+ if(reachable) {
+ localVariableTypes = cloneMap(localVariableTypes);
+ localVariableTypes.remove(exceptionSymbol);
+ jumpToLabel(catchBody, endLabel);
+ canExit = true;
+ }
+ localVariableTypes = cloneMap(afterConditionTypes);
+ localVariableTypes.remove(exceptionSymbol);
+ }
+ // NOTE: if we had one or more conditional catch blocks with no unconditional catch block following them, then
+ // there will be an unconditional rethrow, so the join point can never be reached from the last
+ // conditionExpression.
+ doesNotContinueSequentially();
+
+ if(canExit) {
+ joinOnLabel(endLabel);
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public boolean enterUnaryNode(final UnaryNode unaryNode) {
+ final Expression expr = unaryNode.getExpression();
+ expr.accept(this);
+
+ if(unaryNode.isSelfModifying()) {
+ if(expr instanceof IdentNode) {
+ final IdentNode ident = (IdentNode)expr;
+ onSelfAssignment(ident, unaryNode, getLocalVariableTypeIfBytecode(ident.getSymbol()));
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterVarNode(final VarNode varNode) {
+ if (!reachable) {
+ return false;
+ }
+ final Expression init = varNode.getInit();
+ if(init != null) {
+ init.accept(this);
+ onAssignment(varNode.getName(), init);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean enterWhileNode(final WhileNode whileNode) {
+ if(!reachable) {
+ return false;
+ }
+ if(whileNode.isDoWhile()) {
+ enterDoWhileLoop(whileNode);
+ } else {
+ enterTestFirstLoop(whileNode, null, null, false);
+ }
+ return false;
+ }
+
+ private Map<Symbol, LvarType> getBreakTargetTypes(final BreakableNode target) {
+ // Remove symbols defined in the the blocks that are being broken out of.
+ Map<Symbol, LvarType> types = localVariableTypes;
+ for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
+ final LexicalContextNode node = it.next();
+ if(node instanceof Block) {
+ for(final Symbol symbol: ((Block)node).getSymbols()) {
+ if(localVariableTypes.containsKey(symbol)) {
+ if(types == localVariableTypes) {
+ types = cloneMap(localVariableTypes);
+ }
+ types.remove(symbol);
+ }
+ }
+ }
+ if(node == target) {
+ break;
+ }
+ }
+ return types;
+ }
+
+ /**
+ * Returns the current type of the local variable represented by the symbol. This is the most strict of all
+ * {@code getLocalVariableType*} methods, as it will throw an assertion if the type is null. Therefore, it is only
+ * safe to be invoked on symbols known to be bytecode locals, and only after they have been initialized.
+ * Regardless, it is recommended to use this method in majority of cases, as because of its strictness it is the
+ * best suited for catching missing type calculation bugs early.
+ * @param symbol a symbol representing a bytecode local variable.
+ * @return the current type of the local variable represented by the symbol
+ */
+ private LvarType getLocalVariableType(final Symbol symbol) {
+ final LvarType type = getLocalVariableTypeOrNull(symbol);
+ assert type != null;
+ return type;
+ }
+
+ /**
+ * Gets the type for a local variable if it is a bytecode local, otherwise null. Can be used in circumstances where
+ * the type is irrelevant if the symbol is not a bytecode local. Note that for bytecode locals, it delegates to
+ * {@link #getLocalVariableType(Symbol)}, so it will still assert that the type for such variable is already
+ * defined (that is, not null).
+ * @param symbol the symbol representing the variable.
+ * @return the current variable type, if it is a bytecode local, otherwise null.
+ */
+ private LvarType getLocalVariableTypeIfBytecode(final Symbol symbol) {
+ return symbol.isBytecodeLocal() ? getLocalVariableType(symbol) : null;
+ }
+
+ /**
+ * Gets the type for a variable represented by a symbol, or null if the type is not know. This is the least strict
+ * of all local variable type getters, and as such its use is discouraged except in initialization scenarios (where
+ * a just-defined symbol might still be null).
+ * @param symbol the symbol
+ * @return the current type for the symbol, or null if the type is not known either because the symbol has not been
+ * initialized, or because the symbol does not represent a bytecode local variable.
+ */
+ private LvarType getLocalVariableTypeOrNull(final Symbol symbol) {
+ return localVariableTypes.get(symbol);
+ }
+
+ private JumpTarget getOrCreateJumpTarget(final Label label) {
+ JumpTarget jumpTarget = jumpTargets.get(label);
+ if(jumpTarget == null) {
+ jumpTarget = createJumpTarget(label);
+ }
+ return jumpTarget;
+ }
+
+
+ /**
+ * If there's a join point associated with a label, insert the join point into the flow.
+ * @param label the label to insert a join point for.
+ */
+ private void joinOnLabel(final Label label) {
+ final JumpTarget jumpTarget = jumpTargets.remove(label);
+ if(jumpTarget == null) {
+ return;
+ }
+ assert !jumpTarget.origins.isEmpty();
+ reachable = true;
+ localVariableTypes = getUnionTypes(jumpTarget.types, localVariableTypes);
+ for(final JumpOrigin jumpOrigin: jumpTarget.origins) {
+ setConversion(jumpOrigin.node, jumpOrigin.types, localVariableTypes);
+ }
+ }
+
+ /**
+ * If we're in a try/catch block, add an edge from the specified node to the try node's pre-catch label.
+ */
+ private void jumpToCatchBlock(final JoinPredecessor jumpOrigin) {
+ final Label currentCatchLabel = catchLabels.peek();
+ if(currentCatchLabel != null) {
+ jumpToLabel(jumpOrigin, currentCatchLabel);
+ }
+ }
+
+ private void jumpToLabel(final JoinPredecessor jumpOrigin, final Label label) {
+ jumpToLabel(jumpOrigin, label, localVariableTypes);
+ }
+
+ private void jumpToLabel(final JoinPredecessor jumpOrigin, final Label label, final Map<Symbol, LvarType> types) {
+ getOrCreateJumpTarget(label).addOrigin(jumpOrigin, types);
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ if(lc.isFunctionBody()) {
+ if(reachable) {
+ // reachable==true means we can reach the end of the function without an explicit return statement. We
+ // need to insert a synthetic one then. This logic used to be in Lower.leaveBlock(), but Lower's
+ // reachability analysis (through Terminal.isTerminal() flags) is not precise enough so
+ // Lower$BlockLexicalContext.afterSetStatements will sometimes think the control flow terminates even
+ // when it didn't. Example: function() { switch((z)) { default: {break; } throw x; } }.
+ createSyntheticReturn(block);
+ assert !reachable;
+ }
+ // We must calculate the return type here (and not in leaveFunctionNode) as it can affect the liveness of
+ // the :return symbol and thus affect conversion type liveness calculations for it.
+ calculateReturnType();
+ }
+
+ boolean cloned = false;
+ for(final Symbol symbol: block.getSymbols()) {
+ // Undefine the symbol outside the block
+ if(localVariableTypes.containsKey(symbol)) {
+ if(!cloned) {
+ localVariableTypes = cloneMap(localVariableTypes);
+ cloned = true;
+ }
+ localVariableTypes.remove(symbol);
+ }
+
+ if(symbol.hasSlot()) {
+ final SymbolConversions conversions = symbolConversions.get(symbol);
+ if(conversions != null) {
+ // Potentially make some currently dead types live if they're needed as a source of a type
+ // conversion at a join.
+ conversions.calculateTypeLiveness(symbol);
+ }
+ if(symbol.slotCount() == 0) {
+ // This is a local variable that is never read. It won't need a slot.
+ symbol.setNeedsSlot(false);
+ }
+ }
+ }
+
+ if(reachable) {
+ // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
+ final LabelNode labelNode = lc.getCurrentBlockLabelNode();
+ if(labelNode != null) {
+ jumpToLabel(labelNode, block.getBreakLabel());
+ }
+ }
+ leaveBreakable(block);
+ return block;
+ }
+
+ private void calculateReturnType() {
+ // NOTE: if return type is unknown, then the function does not explicitly return a value. Such a function under
+ // ECMAScript rules returns Undefined, which has Type.OBJECT. We might consider an optimization in the future
+ // where we can return void functions.
+ if(returnType.isUnknown()) {
+ returnType = Type.OBJECT;
+ }
+ }
+
+ private void createSyntheticReturn(final Block body) {
+ final FunctionNode functionNode = lc.getCurrentFunction();
+ final long token = functionNode.getToken();
+ final int finish = functionNode.getFinish();
+ final List<Statement> statements = body.getStatements();
+ final int lineNumber = statements.isEmpty() ? functionNode.getLineNumber() : statements.get(statements.size() - 1).getLineNumber();
+ final IdentNode returnExpr;
+ if(functionNode.isProgram()) {
+ returnExpr = new IdentNode(token, finish, RETURN.symbolName()).setSymbol(getCompilerConstantSymbol(functionNode, RETURN));
+ } else {
+ returnExpr = null;
+ }
+ syntheticReturn = new ReturnNode(lineNumber, token, finish, returnExpr);
+ syntheticReturn.accept(this);
+ }
+
+ /**
+ * Leave a breakable node. If there's a join point associated with its break label (meaning there was at least one
+ * break statement to the end of the node), insert the join point into the flow.
+ * @param breakable the breakable node being left.
+ */
+ private void leaveBreakable(final BreakableNode breakable) {
+ joinOnLabel(breakable.getBreakLabel());
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ // Sets the return type of the function and also performs the bottom-up pass of applying type and conversion
+ // information to nodes as well as doing the calculation on nested functions as required.
+ FunctionNode newFunction = functionNode;
+ final NodeVisitor<LexicalContext> applyChangesVisitor = new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ private boolean inOuterFunction = true;
+ private final Deque<JoinPredecessor> joinPredecessors = new ArrayDeque<>();
+
+ @Override
+ protected boolean enterDefault(final Node node) {
+ if(!inOuterFunction) {
+ return false;
+ }
+ if(node instanceof JoinPredecessor) {
+ joinPredecessors.push((JoinPredecessor)node);
+ }
+ return inOuterFunction;
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode fn) {
+ if(compiler.isOnDemandCompilation()) {
+ // Only calculate nested function local variable types if we're doing eager compilation
+ return false;
+ }
+ inOuterFunction = false;
+ return true;
+ }
+
+ @SuppressWarnings("fallthrough")
+ @Override
+ public Node leaveBinaryNode(final BinaryNode binaryNode) {
+ if(binaryNode.isComparison()) {
+ final Expression lhs = binaryNode.lhs();
+ final Expression rhs = binaryNode.rhs();
+
+ Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
+ boolean newRuntimeNode = false, finalized = false;
+ final TokenType tt = binaryNode.tokenType();
+ switch (tt) {
+ case EQ_STRICT:
+ case NE_STRICT:
+ // Specialize comparison with undefined
+ final Expression undefinedNode = createIsUndefined(binaryNode, lhs, rhs,
+ tt == TokenType.EQ_STRICT ? Request.IS_UNDEFINED : Request.IS_NOT_UNDEFINED);
+ if(undefinedNode != binaryNode) {
+ return undefinedNode;
+ }
+ // Specialize comparison of boolean with non-boolean
+ if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
+ newRuntimeNode = true;
+ cmpWidest = Type.OBJECT;
+ finalized = true;
+ }
+ // fallthrough
+ default:
+ if (newRuntimeNode || cmpWidest.isObject()) {
+ return new RuntimeNode(binaryNode).setIsFinal(finalized);
+ }
+ }
+ } else if(binaryNode.isOptimisticUndecidedType()) {
+ // At this point, we can assign a static type to the optimistic binary ADD operator as now we know
+ // the types of its operands.
+ return binaryNode.decideType();
+ }
+ return binaryNode;
+ }
+
+ @Override
+ protected Node leaveDefault(final Node node) {
+ if(node instanceof JoinPredecessor) {
+ final JoinPredecessor original = joinPredecessors.pop();
+ assert original.getClass() == node.getClass() : original.getClass().getName() + "!=" + node.getClass().getName();
+ return (Node)setLocalVariableConversion(original, (JoinPredecessor)node);
+ }
+ return node;
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ if(inOuterFunction && syntheticReturn != null && lc.isFunctionBody()) {
+ final ArrayList<Statement> stmts = new ArrayList<>(block.getStatements());
+ stmts.add((ReturnNode)syntheticReturn.accept(this));
+ return block.setStatements(lc, stmts);
+ }
+ return super.leaveBlock(block);
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode nestedFunctionNode) {
+ inOuterFunction = true;
+ final FunctionNode newNestedFunction = (FunctionNode)nestedFunctionNode.accept(
+ new LocalVariableTypesCalculator(compiler));
+ lc.replace(nestedFunctionNode, newNestedFunction);
+ return newNestedFunction;
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ final IdentNode original = (IdentNode)joinPredecessors.pop();
+ final Symbol symbol = identNode.getSymbol();
+ if(symbol == null) {
+ assert identNode.isPropertyName();
+ return identNode;
+ } else if(symbol.hasSlot()) {
+ assert !symbol.isScope() || symbol.isParam(); // Only params can be slotted and scoped.
+ assert original.getName().equals(identNode.getName());
+ final LvarType lvarType = identifierLvarTypes.remove(original);
+ if(lvarType != null) {
+ return setLocalVariableConversion(original, identNode.setType(lvarType.type));
+ }
+ // If there's no type, then the identifier must've been in unreachable code. In that case, it can't
+ // have assigned conversions either.
+ assert localVariableConversions.get(original) == null;
+ } else {
+ assert identIsDeadAndHasNoLiveConversions(original);
+ }
+ return identNode;
+ }
+
+ @Override
+ public Node leaveLiteralNode(final LiteralNode<?> literalNode) {
+ //for e.g. ArrayLiteralNodes the initial types may have been narrowed due to the
+ //introduction of optimistic behavior - hence ensure that all literal nodes are
+ //reinitialized
+ return literalNode.initialize(lc);
+ }
+
+ @Override
+ public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
+ final Request request = runtimeNode.getRequest();
+ final boolean isEqStrict = request == Request.EQ_STRICT;
+ if(isEqStrict || request == Request.NE_STRICT) {
+ return createIsUndefined(runtimeNode, runtimeNode.getArgs().get(0), runtimeNode.getArgs().get(1),
+ isEqStrict ? Request.IS_UNDEFINED : Request.IS_NOT_UNDEFINED);
+ }
+ return runtimeNode;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T extends JoinPredecessor> T setLocalVariableConversion(final JoinPredecessor original, final T jp) {
+ // NOTE: can't use Map.remove() as our copy-on-write AST semantics means some nodes appear twice (in
+ // finally blocks), so we need to be able to access conversions for them multiple times.
+ return (T)jp.setLocalVariableConversion(lc, localVariableConversions.get(original));
+ }
+ };
+
+ newFunction = newFunction.setBody(lc, (Block)newFunction.getBody().accept(applyChangesVisitor));
+ newFunction = newFunction.setReturnType(lc, returnType);
+
+
+ newFunction = newFunction.setState(lc, CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED);
+ newFunction = newFunction.setParameters(lc, newFunction.visitParameters(applyChangesVisitor));
+ return newFunction;
+ }
+
+ private static Expression createIsUndefined(final Expression parent, final Expression lhs, final Expression rhs, final Request request) {
+ if (isUndefinedIdent(lhs) || isUndefinedIdent(rhs)) {
+ return new RuntimeNode(parent, request, lhs, rhs);
+ }
+ return parent;
+ }
+
+ private static boolean isUndefinedIdent(final Expression expr) {
+ return expr instanceof IdentNode && "undefined".equals(((IdentNode)expr).getName());
+ }
+
+ private boolean identIsDeadAndHasNoLiveConversions(final IdentNode identNode) {
+ final LocalVariableConversion conv = localVariableConversions.get(identNode);
+ return conv == null || !conv.isLive();
+ }
+
+ private void onAssignment(final IdentNode identNode, final Expression rhs) {
+ onAssignment(identNode, toLvarType(getType(rhs)));
+ }
+
+ private void onAssignment(final IdentNode identNode, final LvarType type) {
+ final Symbol symbol = identNode.getSymbol();
+ assert symbol != null : identNode.getName();
+ if(!symbol.isBytecodeLocal()) {
+ return;
+ }
+ assert type != null;
+ final LvarType finalType;
+ if(type == LvarType.UNDEFINED && getLocalVariableType(symbol) != LvarType.UNDEFINED) {
+ // Explicit assignment of a known undefined local variable to a local variable that is not undefined will
+ // materialize that undefined in the assignment target. Note that assigning known undefined to known
+ // undefined will *not* initialize the variable, e.g. "var x; var y = x;" compiles to no-op.
+ finalType = LvarType.OBJECT;
+ symbol.setFlag(Symbol.HAS_OBJECT_VALUE);
+ } else {
+ finalType = type;
+ }
+ setType(symbol, finalType);
+ // Explicit assignment of an undefined value. Make sure the variable can store an object
+ // TODO: if we communicated the fact to codegen with a flag on the IdentNode that the value was already
+ // undefined before the assignment, we could just ignore it. In general, we could ignore an assignment if we
+ // know that the value assigned is the same as the current value of the variable, but we'd need constant
+ // propagation for that.
+ setIdentifierLvarType(identNode, finalType);
+ // For purposes of type calculation, we consider an assignment to a local variable to be followed by
+ // the catch nodes of the current (if any) try block. This will effectively enforce that narrower
+ // assignments to a local variable in a try block will also have to store a widened value as well. Code
+ // within the try block will be able to keep loading the narrower value, but after the try block only
+ // the widest value will remain live.
+ // Rationale for this is that if there's an use for that variable in any of the catch blocks, or
+ // following the catch blocks, they must use the widest type.
+ // Example:
+ /*
+ Originally:
+ ===========
+ var x;
+ try {
+ x = 1; <-- stores into int slot for x
+ f(x); <-- loads the int slot for x
+ x = 3.14 <-- stores into the double slot for x
+ f(x); <-- loads the double slot for x
+ x = 1; <-- stores into int slot for x
+ f(x); <-- loads the int slot for x
+ } finally {
+ f(x); <-- loads the double slot for x, but can be reached by a path where x is int, so we need
+ to go back and ensure that double values are also always stored along with int
+ values.
+ }
+
+ After correction:
+ =================
+
+ var x;
+ try {
+ x = 1; <-- stores into both int and double slots for x
+ f(x); <-- loads the int slot for x
+ x = 3.14 <-- stores into the double slot for x
+ f(x); <-- loads the double slot for x
+ x = 1; <-- stores into both int and double slots for x
+ f(x); <-- loads the int slot for x
+ } finally {
+ f(x); <-- loads the double slot for x
+ }
+ */
+ jumpToCatchBlock(identNode);
+ }
+
+ private void onSelfAssignment(final IdentNode identNode, final Expression assignment, final LvarType typeOnLoad) {
+ final Symbol symbol = identNode.getSymbol();
+ assert symbol != null : identNode.getName();
+ if(!symbol.isBytecodeLocal()) {
+ return;
+ }
+ final LvarType type = toLvarType(getType(assignment, symbol, typeOnLoad.type));
+ // Self-assignment never produce either a boolean or undefined
+ assert type != null && type != LvarType.UNDEFINED && type != LvarType.BOOLEAN;
+ setType(symbol, type);
+ jumpToCatchBlock(identNode);
+ }
+
+ private void resetJoinPoint(final Label label) {
+ jumpTargets.remove(label);
+ }
+
+ private void setCompilerConstantAsObject(final FunctionNode functionNode, final CompilerConstants cc) {
+ final Symbol symbol = getCompilerConstantSymbol(functionNode, cc);
+ setType(symbol, LvarType.OBJECT);
+ // never mark compiler constants as dead
+ symbolIsUsed(symbol);
+ }
+
+ private static Symbol getCompilerConstantSymbol(final FunctionNode functionNode, final CompilerConstants cc) {
+ return functionNode.getBody().getExistingSymbol(cc.symbolName());
+ }
+
+ private void setConversion(final JoinPredecessor node, final Map<Symbol, LvarType> branchLvarTypes, final Map<Symbol, LvarType> joinLvarTypes) {
+ if(node == null) {
+ return;
+ }
+ if(branchLvarTypes.isEmpty() || joinLvarTypes.isEmpty()) {
+ localVariableConversions.remove(node);
+ }
+
+ LocalVariableConversion conversion = null;
+ if(node instanceof IdentNode) {
+ // conversions on variable assignment in try block are special cases, as they only apply to the variable
+ // being assigned and all other conversions should be ignored.
+ final Symbol symbol = ((IdentNode)node).getSymbol();
+ conversion = createConversion(symbol, branchLvarTypes.get(symbol), joinLvarTypes, null);
+ } else {
+ for(final Map.Entry<Symbol, LvarType> entry: branchLvarTypes.entrySet()) {
+ final Symbol symbol = entry.getKey();
+ final LvarType branchLvarType = entry.getValue();
+ conversion = createConversion(symbol, branchLvarType, joinLvarTypes, conversion);
+ }
+ }
+ if(conversion != null) {
+ localVariableConversions.put(node, conversion);
+ } else {
+ localVariableConversions.remove(node);
+ }
+ }
+
+ private void setIdentifierLvarType(final IdentNode identNode, final LvarType type) {
+ assert type != null;
+ identifierLvarTypes.put(identNode, type);
+ }
+
+ /**
+ * Marks a local variable as having a specific type from this point onward. Invoked by stores to local variables.
+ * @param symbol the symbol representing the variable
+ * @param type the type
+ */
+ @SuppressWarnings("unused")
+ private void setType(final Symbol symbol, final LvarType type) {
+ if(getLocalVariableTypeOrNull(symbol) == type) {
+ return;
+ }
+ assert symbol.hasSlot();
+ assert !symbol.isGlobal();
+ localVariableTypes = localVariableTypes.isEmpty() ? new IdentityHashMap<Symbol, LvarType>() : cloneMap(localVariableTypes);
+ localVariableTypes.put(symbol, type);
+ }
+
+ /**
+ * Set a flag in the symbol marking it as needing to be able to store a value of a particular type. Every symbol for
+ * a local variable will be assigned between 1 and 6 local variable slots for storing all types it is known to need
+ * to store.
+ * @param symbol the symbol
+ */
+ private void symbolIsUsed(final Symbol symbol) {
+ symbolIsUsed(symbol, getLocalVariableType(symbol));
+ }
+
+ /**
+ * Gets the type of the expression, dependent on the current types of the local variables.
+ *
+ * @param expr the expression
+ * @return the current type of the expression dependent on the current types of the local variables.
+ */
+ private Type getType(final Expression expr) {
+ return expr.getType(getSymbolToType());
+ }
+
+ /**
+ * Returns a function object from symbols to their types, used by the expressions to evaluate their type.
+ * {@link BinaryNode} specifically uses identity of the function to cache type calculations. This method makes
+ * sure to return the same function object while the local variable types don't change, and create a new function
+ * object if the local variable types have been changed.
+ * @return a function object representing a mapping from symbols to their types.
+ */
+ private Function<Symbol, Type> getSymbolToType() {
+ if(symbolToType.isStale()) {
+ symbolToType = new SymbolToType();
+ }
+ return symbolToType;
+ }
+
+ private class SymbolToType implements Function<Symbol, Type> {
+ private final Object boundTypes = localVariableTypes;
+ @Override
+ public Type apply(final Symbol t) {
+ return getLocalVariableType(t).type;
+ }
+
+ boolean isStale() {
+ return boundTypes != localVariableTypes;
+ }
+ }
+
+ /**
+ * Gets the type of the expression, dependent on the current types of the local variables and a single overridden
+ * symbol type. Used by type calculation on compound operators to ensure the type of the LHS at the time it was
+ * loaded (which can potentially be different after RHS evaluation, e.g. "var x; x += x = 0;") is preserved for
+ * the calculation.
+ *
+ * @param expr the expression
+ * @param overriddenSymbol the overridden symbol
+ * @param overriddenType the overridden type
+ * @return the current type of the expression dependent on the current types of the local variables and the single
+ * potentially overridden type.
+ */
+ private Type getType(final Expression expr, final Symbol overriddenSymbol, final Type overriddenType) {
+ return expr.getType(getSymbolToType(overriddenSymbol, overriddenType));
+ }
+
+ private Function<Symbol, Type> getSymbolToType(final Symbol overriddenSymbol, final Type overriddenType) {
+ return getLocalVariableType(overriddenSymbol).type == overriddenType ? getSymbolToType() :
+ new SymbolToTypeOverride(overriddenSymbol, overriddenType);
+ }
+
+ private class SymbolToTypeOverride implements Function<Symbol, Type> {
+ private final Function<Symbol, Type> originalSymbolToType = getSymbolToType();
+ private final Symbol overriddenSymbol;
+ private final Type overriddenType;
+
+ SymbolToTypeOverride(final Symbol overriddenSymbol, final Type overriddenType) {
+ this.overriddenSymbol = overriddenSymbol;
+ this.overriddenType = overriddenType;
+ }
+
+ @Override
+ public Type apply(final Symbol symbol) {
+ return symbol == overriddenSymbol ? overriddenType : originalSymbolToType.apply(symbol);
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/Lower.java b/src/jdk/nashorn/internal/codegen/Lower.java
index bf6872fe..a30e79a4 100644
--- a/src/jdk/nashorn/internal/codegen/Lower.java
+++ b/src/jdk/nashorn/internal/codegen/Lower.java
@@ -27,12 +27,15 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
+import java.util.regex.Pattern;
+import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.BaseNode;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
@@ -40,6 +43,7 @@ import jdk.nashorn.internal.ir.BlockLexicalContext;
import jdk.nashorn.internal.ir.BlockStatement;
import jdk.nashorn.internal.ir.BreakNode;
import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.EmptyNode;
@@ -50,12 +54,15 @@ import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JumpStatement;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LoopNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.Symbol;
@@ -68,10 +75,12 @@ import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.CodeInstaller;
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Lower to more primitive operations. After lowering, an AST still has no symbols
@@ -82,18 +91,19 @@ import jdk.nashorn.internal.runtime.Source;
* harder and context dependent to do any code copying after symbols have been
* finalized.
*/
+@Logger(name="lower")
+final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Loggable {
-final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
+ private final DebugLogger log;
- private static final DebugLogger LOG = new DebugLogger("lower");
-
- // needed only to get unique eval id
- private final CodeInstaller<?> installer;
+ // Conservative pattern to test if element names consist of characters valid for identifiers.
+ // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit.
+ private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*");
/**
* Constructor.
*/
- Lower(final CodeInstaller<?> installer) {
+ Lower(final Compiler compiler) {
super(new BlockLexicalContext() {
@Override
@@ -136,40 +146,18 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return block.setIsTerminal(this, false);
}
});
- this.installer = installer;
+
+ this.log = initLogger(compiler.getContext());
}
@Override
- public boolean enterBlock(final Block block) {
- final FunctionNode function = lc.getCurrentFunction();
- if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) {
- new ExpressionStatement(function.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
- }
- return true;
+ public DebugLogger getLogger() {
+ return log;
}
@Override
- public Node leaveBlock(final Block block) {
- //now we have committed the entire statement list to the block, but we need to truncate
- //whatever is after the last terminal. block append won't append past it
-
-
- if (lc.isFunctionBody()) {
- final FunctionNode currentFunction = lc.getCurrentFunction();
- final boolean isProgram = currentFunction.isProgram();
- final Statement last = lc.getLastStatement();
- final ReturnNode returnNode = new ReturnNode(
- last == null ? currentFunction.getLineNumber() : last.getLineNumber(), //TODO?
- currentFunction.getToken(),
- currentFunction.getFinish(),
- isProgram ?
- compilerConstant(RETURN) :
- LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED));
-
- returnNode.accept(this);
- }
-
- return block;
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
}
@Override
@@ -200,6 +188,28 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
}
@Override
+ public Node leaveIndexNode(final IndexNode indexNode) {
+ final String name = getConstantPropertyName(indexNode.getIndex());
+ if (name != null) {
+ // If index node is a constant property name convert index node to access node.
+ assert Token.descType(indexNode.getToken()) == TokenType.LBRACKET;
+ return new AccessNode(indexNode.getToken(), indexNode.getFinish(), indexNode.getBase(), name);
+ }
+ return super.leaveIndexNode(indexNode);
+ }
+
+ // If expression is a primitive literal that is not an array index and does return its string value. Else return null.
+ private static String getConstantPropertyName(final Expression expression) {
+ if (expression instanceof LiteralNode.PrimitiveLiteralNode) {
+ final Object value = ((LiteralNode) expression).getValue();
+ if (value instanceof String && SAFE_PROPERTY_NAME.matcher((String) value).matches()) {
+ return (String) value;
+ }
+ }
+ return null;
+ }
+
+ @Override
public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
final Expression expr = expressionStatement.getExpression();
ExpressionStatement node = expressionStatement;
@@ -222,7 +232,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
}
@Override
- public Node leaveBlockStatement(BlockStatement blockStatement) {
+ public Node leaveBlockStatement(final BlockStatement blockStatement) {
return addStatement(blockStatement);
}
@@ -230,22 +240,24 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
public Node leaveForNode(final ForNode forNode) {
ForNode newForNode = forNode;
- final Node test = forNode.getTest();
- if (!forNode.isForIn() && conservativeAlwaysTrue(test)) {
+ final Expression test = forNode.getTest();
+ if (!forNode.isForIn() && isAlwaysTrue(test)) {
newForNode = forNode.setTest(lc, null);
}
- return addStatement(checkEscape(newForNode));
- }
-
- @Override
- public boolean enterFunctionNode(final FunctionNode functionNode) {
- return !functionNode.isLazy();
+ newForNode = checkEscape(newForNode);
+ if(newForNode.isForIn()) {
+ // Wrap it in a block so its internally created iterator is restricted in scope
+ addStatementEnclosedInBlock(newForNode);
+ } else {
+ addStatement(newForNode);
+ }
+ return newForNode;
}
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
- LOG.info("END FunctionNode: ", functionNode.getName());
+ log.info("END FunctionNode: ", functionNode.getName());
return functionNode.setState(lc, CompilationState.LOWERED);
}
@@ -255,6 +267,16 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
}
@Override
+ public Node leaveIN(final BinaryNode binaryNode) {
+ return new RuntimeNode(binaryNode);
+ }
+
+ @Override
+ public Node leaveINSTANCEOF(final BinaryNode binaryNode) {
+ return new RuntimeNode(binaryNode);
+ }
+
+ @Override
public Node leaveLabelNode(final LabelNode labelNode) {
return addStatement(labelNode);
}
@@ -265,16 +287,35 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return returnNode;
}
+ @Override
+ public Node leaveCaseNode(final CaseNode caseNode) {
+ // Try to represent the case test as an integer
+ final Node test = caseNode.getTest();
+ if (test instanceof LiteralNode) {
+ final LiteralNode<?> lit = (LiteralNode<?>)test;
+ if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) {
+ if (JSType.isRepresentableAsInt(lit.getNumber())) {
+ return caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
+ }
+ }
+ }
+ return caseNode;
+ }
@Override
public Node leaveSwitchNode(final SwitchNode switchNode) {
- return addStatement(switchNode);
+ if(!switchNode.isUniqueInteger()) {
+ // Wrap it in a block so its internally created tag is restricted in scope
+ addStatementEnclosedInBlock(switchNode);
+ } else {
+ addStatement(switchNode);
+ }
+ return switchNode;
}
@Override
public Node leaveThrowNode(final ThrowNode throwNode) {
- addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
- return throwNode;
+ return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
}
private static Node ensureUniqueNamesIn(final Node node) {
@@ -308,12 +349,12 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
final long token = tryNode.getToken();
final int finish = tryNode.getFinish();
- final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all"));
+ final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName(CompilerConstants.EXCEPTION_PREFIX.symbolName()));
- final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW));
+ final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), true));
assert catchBody.isTerminal(); //ends with throw, so terminal
- final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW);
+ final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, true);
final Block catchAllBlock = new Block(token, finish, catchAllNode);
//catchallblock -> catchallnode (catchnode) -> exception -> throw
@@ -369,12 +410,16 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
@Override
public Node leaveBreakNode(final BreakNode breakNode) {
- return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabel()));
+ return leaveJumpStatement(breakNode);
}
@Override
public Node leaveContinueNode(final ContinueNode continueNode) {
- return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabel()));
+ return leaveJumpStatement(continueNode);
+ }
+
+ private Node leaveJumpStatement(final JumpStatement jump) {
+ return copy(jump, (Node)jump.getTarget(Lower.this.lc));
}
@Override
@@ -425,7 +470,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
final Block finallyBody = tryNode.getFinallyBody();
if (finallyBody == null) {
- return addStatement(tryNode);
+ return addStatement(ensureUnconditionalCatch(tryNode));
}
/*
@@ -468,7 +513,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
if (tryNode.getCatchBlocks().isEmpty()) {
newTryNode = tryNode.setFinallyBody(null);
} else {
- Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), tryNode.setFinallyBody(null));
+ final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), ensureUnconditionalCatch(tryNode.setFinallyBody(null)));
newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
}
@@ -481,6 +526,18 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return spliceFinally(newTryNode, rethrows, finallyBody);
}
+ private TryNode ensureUnconditionalCatch(final TryNode tryNode) {
+ final List<CatchNode> catches = tryNode.getCatches();
+ if(catches == null || catches.isEmpty() || catches.get(catches.size() - 1).getExceptionCondition() == null) {
+ return tryNode;
+ }
+ // If the last catch block is conditional, add an unconditional rethrow block
+ final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks());
+
+ newCatchBlocks.add(catchAllBlock(tryNode));
+ return tryNode.setCatchBlocks(newCatchBlocks);
+ }
+
@Override
public Node leaveVarNode(final VarNode varNode) {
addStatement(varNode);
@@ -492,12 +549,12 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
@Override
public Node leaveWhileNode(final WhileNode whileNode) {
- final Node test = whileNode.getTest();
+ final Expression test = whileNode.getTest();
final Block body = whileNode.getBody();
- if (conservativeAlwaysTrue(test)) {
+ if (isAlwaysTrue(test)) {
//turn it into a for node without a test.
- final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), null, null, body, null, ForNode.IS_FOR).accept(this);
+ final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, 0).accept(this);
lc.replace(whileNode, forNode);
return forNode;
}
@@ -535,16 +592,13 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
private String evalLocation(final IdentNode node) {
final Source source = lc.getCurrentFunction().getSource();
final int pos = node.position();
- // Code installer is null when running with --compile-only, use 0 as id in that case
- final long id = installer == null ? 0 : installer.getUniqueEvalId();
return new StringBuilder().
append(source.getName()).
append('#').
append(source.getLine(pos)).
append(':').
append(source.getColumn(pos)).
- append("<eval>@").
- append(id).
+ append("<eval>").
toString();
}
@@ -571,23 +625,17 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
// 'eval' call with at least one argument
if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
- final FunctionNode currentFunction = lc.getCurrentFunction();
- return callNode.setEvalArgs(
- new CallNode.EvalArgs(
- (Expression)ensureUniqueNamesIn(args.get(0)).accept(this),
- compilerConstant(THIS),
- evalLocation(callee),
- currentFunction.isStrict()));
+ final List<Expression> evalArgs = new ArrayList<>(args.size());
+ for(final Expression arg: args) {
+ evalArgs.add((Expression)ensureUniqueNamesIn(arg).accept(this));
+ }
+ return callNode.setEvalArgs(new CallNode.EvalArgs(evalArgs, evalLocation(callee)));
}
}
return callNode;
}
- private static boolean conservativeAlwaysTrue(final Node node) {
- return node == null || ((node instanceof LiteralNode) && Boolean.TRUE.equals(((LiteralNode<?>)node).getValue()));
- }
-
/**
* Helper that given a loop body makes sure that it is not terminal if it
* has a continue that leads to the loop header or to outer loops' loop
@@ -610,7 +658,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
@Override
public Node leaveContinueNode(final ContinueNode node) {
// all inner loops have been popped.
- if (lex.contains(lex.getContinueTo(node.getLabel()))) {
+ if (lex.contains(node.getTarget(lex))) {
escapes.add(node);
}
return node;
@@ -620,10 +668,11 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return !escapes.isEmpty();
}
- private LoopNode checkEscape(final LoopNode loopNode) {
+ @SuppressWarnings("unchecked")
+ private <T extends LoopNode> T checkEscape(final T loopNode) {
final boolean escapes = controlFlowEscapes(lc, loopNode.getBody());
if (escapes) {
- return loopNode.
+ return (T)loopNode.
setBody(lc, loopNode.getBody().setIsTerminal(lc, false)).
setControlFlowEscapes(lc, escapes);
}
@@ -636,6 +685,14 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return statement;
}
+ private void addStatementEnclosedInBlock(final Statement stmt) {
+ BlockStatement b = BlockStatement.createReplacement(stmt, Collections.<Statement>singletonList(stmt));
+ if(stmt.isTerminal()) {
+ b = b.setBlock(b.getBlock().setIsTerminal(null, true));
+ }
+ addStatement(b);
+ }
+
/**
* An internal expression has a symbol that is tagged internal. Check if
* this is such a node
@@ -644,7 +701,10 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
* @return true if internal, false otherwise
*/
private static boolean isInternalExpression(final Expression expression) {
- final Symbol symbol = expression.getSymbol();
+ if (!(expression instanceof IdentNode)) {
+ return false;
+ }
+ final Symbol symbol = ((IdentNode)expression).getSymbol();
return symbol != null && symbol.isInternal();
}
@@ -656,8 +716,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
* @return true if an assignment to eval result, false otherwise
*/
private static boolean isEvalResultAssignment(final Node expression) {
- Node e = expression;
- assert e.tokenType() != TokenType.DISCARD; //there are no discards this early anymore
+ final Node e = expression;
if (e instanceof BinaryNode) {
final Node lhs = ((BinaryNode)e).lhs();
if (lhs instanceof IdentNode) {
@@ -666,5 +725,4 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
}
return false;
}
-
}
diff --git a/src/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk/nashorn/internal/codegen/MapCreator.java
index 436622bd..1bec86fc 100644
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/src/jdk/nashorn/internal/codegen/MapCreator.java
@@ -34,52 +34,58 @@ import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.SpillProperty;
/**
* Class that creates PropertyMap sent to script object constructors.
+ * @param <T> value type for tuples, e.g. Symbol
*/
-public class MapCreator {
+public class MapCreator<T> {
/** Object structure for objects associated with this map */
private final Class<?> structure;
/** key set for object map */
- final List<String> keys;
-
- /** corresponding symbol set for object map */
- final List<Symbol> symbols;
+ private final List<MapTuple<T>> tuples;
/**
* Constructor
*
* @param structure structure to generate map for (a JO subclass)
- * @param keys list of keys for map
- * @param symbols list of symbols for map
+ * @param tuples list of tuples for map
*/
- MapCreator(final Class<?> structure, final List<String> keys, final List<Symbol> symbols) {
+ MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) {
this.structure = structure;
- this.keys = keys;
- this.symbols = symbols;
+ this.tuples = tuples;
}
/**
* Constructs a property map based on a set of fields.
*
- * @param hasArguments does the created object have an "arguments" property
+ * @param hasArguments does the created object have an "arguments" property
* @param fieldCount Number of fields in use.
- * @param fieldMaximum Number of fields available.
- *
+ * @param fieldMaximum Number of fields available.
+ * @param evalCode is this property map created for 'eval' code?
* @return New map populated with accessor properties.
*/
- PropertyMap makeFieldMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum) {
+ PropertyMap makeFieldMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum, final boolean evalCode) {
final List<Property> properties = new ArrayList<>();
- assert keys != null;
+ assert tuples != null;
- for (int i = 0, length = keys.size(); i < length; i++) {
- final String key = keys.get(i);
- final Symbol symbol = symbols.get(i);
+ for (final MapTuple<T> tuple : tuples) {
+ final String key = tuple.key;
+ final Symbol symbol = tuple.symbol;
+ final Class<?> initialType = tuple.getValueType();
if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
- properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex()));
+ final int flags = getPropertyFlags(symbol, hasArguments, evalCode);
+ final Property property = new AccessorProperty(
+ key,
+ flags,
+ structure,
+ symbol.getFieldIndex(),
+ initialType);
+ properties.add(property);
}
}
@@ -89,14 +95,20 @@ public class MapCreator {
PropertyMap makeSpillMap(final boolean hasArguments) {
final List<Property> properties = new ArrayList<>();
int spillIndex = 0;
- assert keys != null;
+ assert tuples != null;
- for (int i = 0, length = keys.size(); i < length; i++) {
- final String key = keys.get(i);
- final Symbol symbol = symbols.get(i);
+ for (final MapTuple<T> tuple : tuples) {
+ final String key = tuple.key;
+ final Symbol symbol = tuple.symbol;
+ //TODO initial type is object here no matter what. Is that right?
if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
- properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), spillIndex++));
+ final int flags = getPropertyFlags(symbol, hasArguments, false);
+ properties.add(
+ new SpillProperty(
+ key,
+ flags,
+ spillIndex++));
}
}
@@ -111,34 +123,44 @@ public class MapCreator {
*
* @return flags to use for fields
*/
- protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) {
+ static int getPropertyFlags(final Symbol symbol, final boolean hasArguments, final boolean evalCode) {
int flags = 0;
if (symbol.isParam()) {
- flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER;
+ flags |= Property.IS_PARAMETER;
}
if (hasArguments) {
- flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS;
+ flags |= Property.HAS_ARGUMENTS;
}
- if (symbol.isScope()) {
+ // See ECMA 5.1 10.5 Declaration Binding Instantiation.
+ // Step 2 If code is eval code, then let configurableBindings
+ // be true else let configurableBindings be false.
+ // We have to make vars, functions declared in 'eval' code
+ // configurable. But vars, functions from any other code is
+ // not configurable.
+ if (symbol.isScope() && !evalCode) {
flags |= Property.NOT_CONFIGURABLE;
}
- if (symbol.canBePrimitive()) {
- flags |= Property.CAN_BE_PRIMITIVE;
+ if (symbol.isFunctionDeclaration()) {
+ flags |= Property.IS_FUNCTION_DECLARATION;
+ }
+
+ if (symbol.isConst()) {
+ flags |= Property.NOT_WRITABLE;
}
- if (symbol.canBeUndefined()) {
- flags |= Property.CAN_BE_UNDEFINED;
+ if (symbol.isBlockScoped()) {
+ flags |= Property.IS_LEXICAL_BINDING;
}
- if (symbol.isFunctionDeclaration()) {
- flags |= Property.IS_FUNCTION_DECLARATION;
+ // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError.
+ if (symbol.isBlockScoped() && symbol.isScope()) {
+ flags |= Property.NEEDS_DECLARATION;
}
return flags;
}
-
}
diff --git a/src/jdk/nashorn/internal/codegen/MapTuple.java b/src/jdk/nashorn/internal/codegen/MapTuple.java
new file mode 100644
index 00000000..024c3d67
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/MapTuple.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Symbol;
+
+/**
+ * A tuple of values used for map creation
+ * @param <T> value type
+ */
+class MapTuple<T> {
+ final String key;
+ final Symbol symbol;
+ final Type type;
+ final T value;
+
+ MapTuple(final String key, final Symbol symbol, final Type type) {
+ this(key, symbol, type, null);
+ }
+
+ MapTuple(final String key, final Symbol symbol, final Type type, final T value) {
+ this.key = key;
+ this.symbol = symbol;
+ this.type = type;
+ this.value = value;
+ }
+
+ public Class<?> getValueType() {
+ return OBJECT_FIELDS_ONLY ? Object.class : null; //until proven otherwise we are undefined, see NASHORN-592 int.class;
+ }
+
+ boolean isPrimitive() {
+ return !OBJECT_FIELDS_ONLY && getValueType().isPrimitive() && getValueType() != boolean.class;
+ }
+
+ @Override
+ public String toString() {
+ return "[key=" + key + ", symbol=" + symbol + ", value=" + value + " (" + (value == null ? "null" : value.getClass().getSimpleName()) +")]";
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index 91129ece..362a7363 100644
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -43,6 +43,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IFNULL;
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ;
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE;
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT;
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE;
import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF;
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
@@ -64,11 +68,17 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
import java.io.PrintStream;
import java.lang.reflect.Array;
+import java.util.Collection;
import java.util.EnumSet;
+import java.util.IdentityHashMap;
import java.util.List;
+import java.util.Map;
import jdk.internal.dynalink.support.NameCodec;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -81,17 +91,25 @@ import jdk.nashorn.internal.codegen.types.NumericType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.JoinPredecessor;
import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.ArgumentSetter;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.RewriteException;
+import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.options.Options;
/**
@@ -111,27 +129,34 @@ public class MethodEmitter implements Emitter {
/** The ASM MethodVisitor we are plugged into */
private final MethodVisitor method;
- /** Current type stack for current evaluation */
- private Label.Stack stack;
-
/** Parent classEmitter representing the class of this method */
private final ClassEmitter classEmitter;
/** FunctionNode representing this method, or null if none exists */
protected FunctionNode functionNode;
+ /** Current type stack for current evaluation */
+ private Label.Stack stack;
+
/** Check whether this emitter ever has a function return point */
private boolean hasReturn;
- /** The script environment */
- private final ScriptEnvironment env;
+ private boolean preventUndefinedLoad;
+
+ /**
+ * Map of live local variable definitions.
+ */
+ private final Map<Symbol, LocalVariableDef> localVariableDefs = new IdentityHashMap<>();
+
+ /** The context */
+ private final Context context;
/** Threshold in chars for when string constants should be split */
static final int LARGE_STRING_THRESHOLD = 32 * 1024;
/** Debug flag, should we dump all generated bytecode along with stacks? */
- private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug");
- private static final boolean DEBUG = LOG.isEnabled();
+ private final DebugLogger log;
+ private final boolean debug;
/** dump stack on a particular line, or -1 if disabled */
private static final int DEBUG_TRACE_LINE;
@@ -153,6 +178,9 @@ public class MethodEmitter implements Emitter {
/** Bootstrap for runtime node indy:s */
private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor());
+ /** Bootstrap for array populators */
+ private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor());
+
/**
* Constructor - internal use from ClassEmitter only
* @see ClassEmitter#method
@@ -173,11 +201,13 @@ public class MethodEmitter implements Emitter {
* @param functionNode a function node representing this method
*/
MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) {
- this.env = classEmitter.getEnv();
+ this.context = classEmitter.getContext();
this.classEmitter = classEmitter;
this.method = method;
this.functionNode = functionNode;
this.stack = null;
+ this.log = context.getLogger(CodeGenerator.class);
+ this.debug = log.isEnabled();
}
/**
@@ -203,6 +233,14 @@ public class MethodEmitter implements Emitter {
classEmitter.endMethod(this);
}
+ boolean isReachable() {
+ return stack != null;
+ }
+
+ private void doesNotContinueSequentially() {
+ stack = null;
+ }
+
private void newStack() {
stack = new Label.Stack();
}
@@ -216,7 +254,7 @@ public class MethodEmitter implements Emitter {
* Push a type to the existing stack
* @param type the type
*/
- private void pushType(final Type type) {
+ void pushType(final Type type) {
if (type != null) {
stack.push(type);
}
@@ -230,7 +268,7 @@ public class MethodEmitter implements Emitter {
* @return the type that was retrieved
*/
private Type popType(final Type expected) {
- final Type type = stack.pop();
+ final Type type = popType();
assert type.isObject() && expected.isObject() ||
type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
return type;
@@ -246,26 +284,40 @@ public class MethodEmitter implements Emitter {
}
/**
- * Pop a type from the existing stack, ensuring that it is numeric,
- * assert if not
+ * Pop a type from the existing stack, ensuring that it is numeric. Boolean type is popped as int type.
*
* @return the type
*/
private NumericType popNumeric() {
- final Type type = stack.pop();
- assert type.isNumeric() : type + " is not numeric";
+ final Type type = popType();
+ if(type.isBoolean()) {
+ // Booleans are treated as int for purposes of arithmetic operations
+ return Type.INT;
+ }
+ assert type.isNumeric();
return (NumericType)type;
}
/**
* Pop a type from the existing stack, ensuring that it is an integer type
- * (integer or long), assert if not
+ * (integer or long). Boolean type is popped as int type.
*
* @return the type
*/
+ private BitwiseType popBitwise() {
+ final Type type = popType();
+ if(type == Type.BOOLEAN) {
+ return Type.INT;
+ }
+ return (BitwiseType)type;
+ }
+
private BitwiseType popInteger() {
- final Type type = stack.pop();
- assert type.isInteger() || type.isLong() : type + " is not an integer or long";
+ final Type type = popType();
+ if(type == Type.BOOLEAN) {
+ return Type.INT;
+ }
+ assert type == Type.INT;
return (BitwiseType)type;
}
@@ -276,7 +328,7 @@ public class MethodEmitter implements Emitter {
* @return the type
*/
private ArrayType popArray() {
- final Type type = stack.pop();
+ final Type type = popType();
assert type.isArray() : type;
return (ArrayType)type;
}
@@ -307,13 +359,14 @@ public class MethodEmitter implements Emitter {
* object type on the stack
*
* @param classDescriptor class descriptor for the object type
+ * @param type the type of the new object
*
* @return the method emitter
*/
- MethodEmitter _new(final String classDescriptor) {
+ MethodEmitter _new(final String classDescriptor, final Type type) {
debug("new", classDescriptor);
method.visitTypeInsn(NEW, classDescriptor);
- pushType(Type.OBJECT);
+ pushType(type);
return this;
}
@@ -326,7 +379,7 @@ public class MethodEmitter implements Emitter {
* @return the method emitter
*/
MethodEmitter _new(final Class<?> clazz) {
- return _new(className(clazz));
+ return _new(className(clazz), Type.typeFor(clazz));
}
/**
@@ -358,25 +411,40 @@ public class MethodEmitter implements Emitter {
debug("dup", depth);
switch (depth) {
- case 0:
+ case 0: {
+ final int l0 = stack.getTopLocalLoad();
pushType(peekType());
+ stack.markLocalLoad(l0);
break;
+ }
case 1: {
+ final int l0 = stack.getTopLocalLoad();
final Type p0 = popType();
+ final int l1 = stack.getTopLocalLoad();
final Type p1 = popType();
pushType(p0);
+ stack.markLocalLoad(l0);
pushType(p1);
+ stack.markLocalLoad(l1);
pushType(p0);
+ stack.markLocalLoad(l0);
break;
}
case 2: {
+ final int l0 = stack.getTopLocalLoad();
final Type p0 = popType();
+ final int l1 = stack.getTopLocalLoad();
final Type p1 = popType();
+ final int l2 = stack.getTopLocalLoad();
final Type p2 = popType();
pushType(p0);
+ stack.markLocalLoad(l0);
pushType(p2);
+ stack.markLocalLoad(l2);
pushType(p1);
+ stack.markLocalLoad(l1);
pushType(p0);
+ stack.markLocalLoad(l0);
break;
}
default:
@@ -398,13 +466,22 @@ public class MethodEmitter implements Emitter {
debug("dup2");
if (peekType().isCategory2()) {
+ final int l0 = stack.getTopLocalLoad();
pushType(peekType());
+ stack.markLocalLoad(l0);
} else {
- final Type type = get2();
- pushType(type);
- pushType(type);
- pushType(type);
- pushType(type);
+ final int l0 = stack.getTopLocalLoad();
+ final Type p0 = popType();
+ final int l1 = stack.getTopLocalLoad();
+ final Type p1 = popType();
+ pushType(p0);
+ stack.markLocalLoad(l0);
+ pushType(p1);
+ stack.markLocalLoad(l1);
+ pushType(p0);
+ stack.markLocalLoad(l0);
+ pushType(p1);
+ stack.markLocalLoad(l1);
}
method.visitInsn(DUP2);
return this;
@@ -454,35 +531,42 @@ public class MethodEmitter implements Emitter {
MethodEmitter swap() {
debug("swap");
+ final int l0 = stack.getTopLocalLoad();
final Type p0 = popType();
+ final int l1 = stack.getTopLocalLoad();
final Type p1 = popType();
p0.swap(method, p1);
pushType(p0);
+ stack.markLocalLoad(l0);
pushType(p1);
- debug("after ", p0, p1);
+ stack.markLocalLoad(l1);
return this;
}
- /**
- * Add a local variable. This is a nop if the symbol has no slot
- *
- * @param symbol symbol for the local variable
- * @param start start of scope
- * @param end end of scope
- */
- void localVariable(final Symbol symbol, final Label start, final Label end) {
- if (!symbol.hasSlot()) {
- return;
- }
-
- String name = symbol.getName();
-
- if (name.equals(THIS.symbolName())) {
- name = THIS_DEBUGGER.symbolName();
+ void pack() {
+ final Type type = peekType();
+ if (type.isInteger()) {
+ convert(PRIMITIVE_FIELD_TYPE);
+ } else if (type.isLong()) {
+ //nop
+ } else if (type.isNumber()) {
+ invokestatic("java/lang/Double", "doubleToRawLongBits", "(D)J");
+ } else {
+ assert false : type + " cannot be packed!";
}
+ //all others are nops, objects aren't packed
+ }
- method.visitLocalVariable(name, symbol.getSymbolType().getDescriptor(), null, start.getLabel(), end.getLabel(), symbol.getSlot());
+ /**
+ * Initializes a bytecode method parameter
+ * @param symbol the symbol for the parameter
+ * @param type the type of the parameter
+ * @param start the label for the start of the method
+ */
+ void initializeMethodParameter(final Symbol symbol, final Type type, final Label start) {
+ assert symbol.isBytecodeLocal();
+ localVariableDefs.put(symbol, new LocalVariableDef(start.getLabel(), type));
}
/**
@@ -550,8 +634,8 @@ public class MethodEmitter implements Emitter {
*/
MethodEmitter shr() {
debug("shr");
- popType(Type.INT);
- pushType(popInteger().shr(method));
+ popInteger();
+ pushType(popBitwise().shr(method));
return this;
}
@@ -563,21 +647,21 @@ public class MethodEmitter implements Emitter {
*/
MethodEmitter shl() {
debug("shl");
- popType(Type.INT);
- pushType(popInteger().shl(method));
+ popInteger();
+ pushType(popBitwise().shl(method));
return this;
}
/**
- * Pops two integer types from the stack, performs a bitwise arithetic shift right and pushes
+ * Pops two integer types from the stack, performs a bitwise arithmetic shift right and pushes
* the result. The shift count, the first element, must be INT.
*
* @return the method emitter
*/
MethodEmitter sar() {
debug("sar");
- popType(Type.INT);
- pushType(popInteger().sar(method));
+ popInteger();
+ pushType(popBitwise().sar(method));
return this;
}
@@ -586,9 +670,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter neg() {
+ MethodEmitter neg(final int programPoint) {
debug("neg");
- pushType(popNumeric().neg(method));
+ pushType(popNumeric().neg(method, programPoint));
return this;
}
@@ -599,20 +683,49 @@ public class MethodEmitter implements Emitter {
* @param recovery label pointing to start of catch block
*/
void _catch(final Label recovery) {
- stack.clear();
- stack.push(Type.OBJECT);
+ // While in JVM a catch block can be reached through normal control flow, our code generator never does this,
+ // so we might as well presume there's no stack on entry.
+ assert stack == null;
+ recovery.onCatch();
label(recovery);
+ beginCatchBlock();
}
/**
+ * Add any number of labels for the start of a catch block and push the exception to the
+ * stack
+ *
+ * @param recoveries labels pointing to start of catch block
+ */
+ void _catch(final Collection<Label> recoveries) {
+ assert stack == null;
+ for(final Label l: recoveries) {
+ label(l);
+ }
+ beginCatchBlock();
+ }
+
+ private void beginCatchBlock() {
+ // It can happen that the catch label wasn't marked as reachable. They are marked as reachable if there's an
+ // assignment in the try block, but it's possible that there was none.
+ if(!isReachable()) {
+ newStack();
+ }
+ pushType(Type.typeFor(Throwable.class));
+ }
+ /**
* Start a try/catch block.
*
* @param entry start label for try
* @param exit end label for try
* @param recovery start label for catch
* @param typeDescriptor type descriptor for exception
+ * @param isOptimismHandler true if this is a hander for {@code UnwarrantedOptimismException}. Normally joining on a
+ * catch handler kills temporary variables, but optimism handlers are an exception, as they need to capture
+ * temporaries as well, so they must remain live.
*/
- void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor) {
+ private void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor, final boolean isOptimismHandler) {
+ recovery.joinFromTry(entry.getStack(), isOptimismHandler);
method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), typeDescriptor);
}
@@ -625,7 +738,7 @@ public class MethodEmitter implements Emitter {
* @param clazz exception class
*/
void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) {
- method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), CompilerConstants.className(clazz));
+ _try(entry, exit, recovery, CompilerConstants.className(clazz), clazz == UnwarrantedOptimismException.class);
}
/**
@@ -636,9 +749,12 @@ public class MethodEmitter implements Emitter {
* @param recovery start label for catch
*/
void _try(final Label entry, final Label exit, final Label recovery) {
- _try(entry, exit, recovery, (String)null);
+ _try(entry, exit, recovery, (String)null, false);
}
+ void markLabelAsOptimisticCatchHandler(final Label label, final int liveLocalCount) {
+ label.markAsOptimisticCatchHandler(stack, liveLocalCount);
+ }
/**
* Load the constants array
@@ -665,6 +781,12 @@ public class MethodEmitter implements Emitter {
return this;
}
+ MethodEmitter loadForcedInitializer(final Type type) {
+ debug("load forced initializer ", type);
+ pushType(type.loadForcedInitializer(method));
+ return this;
+ }
+
/**
* Push the empty value for the given type, i.e. EMPTY.
*
@@ -805,22 +927,36 @@ public class MethodEmitter implements Emitter {
}
/**
- * Push a local variable to the stack. If the symbol representing
- * the local variable doesn't have a slot, this is a NOP
+ * Pushes the value of an identifier to the stack. If the identifier does not represent a local variable or a
+ * parameter, this will be a no-op.
+ *
+ * @param ident the identifier for the variable being loaded.
*
- * @param symbol the symbol representing the local variable.
+ * @return the method emitter
+ */
+ MethodEmitter load(final IdentNode ident) {
+ return load(ident.getSymbol(), ident.getType());
+ }
+
+ /**
+ * Pushes the value of the symbol to the stack with the specified type. No type conversion is being performed, and
+ * the type is only being used if the symbol addresses a local variable slot. The value of the symbol is loaded if
+ * it addresses a local variable slot, or it is a parameter (in which case it can also be loaded from a vararg array
+ * or the arguments object). If it is neither, the operation is a no-op.
*
+ * @param symbol the symbol addressing the value being loaded
+ * @param type the presumed type of the value when it is loaded from a local variable slot
* @return the method emitter
*/
- MethodEmitter load(final Symbol symbol) {
+ MethodEmitter load(final Symbol symbol, final Type type) {
assert symbol != null;
if (symbol.hasSlot()) {
- final int slot = symbol.getSlot();
- debug("load symbol", symbol.getName(), " slot=", slot);
- final Type type = symbol.getSymbolType().load(method, slot);
- pushType(type == Type.OBJECT && symbol.isThis() ? Type.THIS : type);
+ final int slot = symbol.getSlot(type);
+ debug("load symbol", symbol.getName(), " slot=", slot, "type=", type);
+ load(type, slot);
+ // _try(new Label("dummy"), new Label("dummy2"), recovery);
+ // method.visitTryCatchBlock(new Label(), arg1, arg2, arg3);
} else if (symbol.isParam()) {
- assert !symbol.isScope();
assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
final int index = symbol.getFieldIndex();
if (functionNode.needsArguments()) {
@@ -841,7 +977,7 @@ public class MethodEmitter implements Emitter {
}
/**
- * Push a local variable to the stack, given an explicit bytecode slot
+ * Push a local variable to the stack, given an explicit bytecode slot.
* This is used e.g. for stub generation where we know where items like
* "this" and "scope" reside.
*
@@ -853,7 +989,11 @@ public class MethodEmitter implements Emitter {
MethodEmitter load(final Type type, final int slot) {
debug("explicit load", type, slot);
final Type loadType = type.load(method, slot);
+ assert loadType != null;
pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType);
+ assert !preventUndefinedLoad || (slot < stack.localVariableTypes.size() && stack.localVariableTypes.get(slot) != Type.UNKNOWN)
+ : "Attempted load of uninitialized slot " + slot + " (as type " + type + ")";
+ stack.markLocalLoad(slot);
return this;
}
@@ -861,7 +1001,7 @@ public class MethodEmitter implements Emitter {
if (functionNode == null) {
return slot == CompilerConstants.JAVA_THIS.slot();
}
- final int thisSlot = compilerConstant(THIS).getSlot();
+ final int thisSlot = getCompilerConstantSymbol(THIS).getSlot(Type.OBJECT);
assert !functionNode.needsCallee() || thisSlot == 1; // needsCallee -> thisSlot == 1
assert functionNode.needsCallee() || thisSlot == 0; // !needsCallee -> thisSlot == 0
return slot == thisSlot;
@@ -883,7 +1023,7 @@ public class MethodEmitter implements Emitter {
return this;
}
- private Symbol compilerConstant(final CompilerConstants cc) {
+ private Symbol getCompilerConstantSymbol(final CompilerConstants cc) {
return functionNode.getBody().getExistingSymbol(cc.symbolName());
}
@@ -893,22 +1033,46 @@ public class MethodEmitter implements Emitter {
* @return if this method has a slot allocated for the scope variable.
*/
boolean hasScope() {
- return compilerConstant(SCOPE).hasSlot();
+ return getCompilerConstantSymbol(SCOPE).hasSlot();
}
MethodEmitter loadCompilerConstant(final CompilerConstants cc) {
- final Symbol symbol = compilerConstant(cc);
+ return loadCompilerConstant(cc, null);
+ }
+
+ MethodEmitter loadCompilerConstant(final CompilerConstants cc, final Type type) {
if (cc == SCOPE && peekType() == Type.SCOPE) {
dup();
return this;
}
- return load(symbol);
+ return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc));
+ }
+
+ MethodEmitter loadScope() {
+ return loadCompilerConstant(SCOPE).checkcast(Scope.class);
+ }
+
+ MethodEmitter setSplitState(final int state) {
+ return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE);
}
void storeCompilerConstant(final CompilerConstants cc) {
- final Symbol symbol = compilerConstant(cc);
+ storeCompilerConstant(cc, null);
+ }
+
+ void storeCompilerConstant(final CompilerConstants cc, final Type type) {
+ final Symbol symbol = getCompilerConstantSymbol(cc);
+ if(!symbol.hasSlot()) {
+ return;
+ }
debug("store compiler constant ", symbol);
- store(symbol);
+ store(symbol, type != null ? type : getCompilerConstantType(cc));
+ }
+
+ private static Type getCompilerConstantType(final CompilerConstants cc) {
+ final Class<?> constantType = cc.type();
+ assert constantType != null;
+ return Type.typeFor(constantType);
}
/**
@@ -940,48 +1104,215 @@ public class MethodEmitter implements Emitter {
/**
* Pop a value from the stack and store it in a local variable represented
- * by the given symbol. If the symbol has no slot, this is a NOP
+ * by the given identifier. If the symbol has no slot, this is a NOP
*
- * @param symbol symbol to store stack to
+ * @param ident identifier to store stack to
*/
- void store(final Symbol symbol) {
+ void store(final IdentNode ident) {
+ final Type type = ident.getType();
+ final Symbol symbol = ident.getSymbol();
+ if(type == Type.UNDEFINED) {
+ assert peekType() == Type.UNDEFINED;
+ store(symbol, Type.OBJECT);
+ } else {
+ store(symbol, type);
+ }
+ }
+
+ /**
+ * Represents a definition of a local variable with a type. Used for local variable table building.
+ */
+ private static class LocalVariableDef {
+ // The start label from where this definition lives.
+ private final jdk.internal.org.objectweb.asm.Label label;
+ // The currently live type of the local variable.
+ private final Type type;
+
+ LocalVariableDef(final jdk.internal.org.objectweb.asm.Label label, final Type type) {
+ this.label = label;
+ this.type = type;
+ }
+
+ }
+
+ void closeLocalVariable(final Symbol symbol, final Label label) {
+ final LocalVariableDef def = localVariableDefs.get(symbol);
+ if(def != null) {
+ endLocalValueDef(symbol, def, label.getLabel());
+ }
+ if(isReachable()) {
+ markDeadLocalVariable(symbol);
+ }
+ }
+
+ void markDeadLocalVariable(final Symbol symbol) {
+ if(!symbol.isDead()) {
+ markDeadSlots(symbol.getFirstSlot(), symbol.slotCount());
+ }
+ }
+
+ void markDeadSlots(final int firstSlot, final int slotCount) {
+ stack.markDeadLocalVariables(firstSlot, slotCount);
+ }
+
+ private void endLocalValueDef(final Symbol symbol, final LocalVariableDef def, final jdk.internal.org.objectweb.asm.Label label) {
+ String name = symbol.getName();
+ if (name.equals(THIS.symbolName())) {
+ name = THIS_DEBUGGER.symbolName();
+ }
+ method.visitLocalVariable(name, def.type.getDescriptor(), null, def.label, label, symbol.getSlot(def.type));
+ }
+
+ void store(final Symbol symbol, final Type type) {
+ store(symbol, type, true);
+ }
+
+ /**
+ * Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either
+ * a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also
+ * do the bookeeping of the local variable table as well as mark values in all alternative slots for the symbol as
+ * dead. In this regard it differs from {@link #storeHidden(Type, int)}.
+ *
+ * @param symbol the symbol to store into.
+ * @param type the type to store
+ * @param onlySymbolLiveValue if true, this is the sole live value for the symbol. If false, currently live values should
+ * be kept live.
+ */
+ void store(final Symbol symbol, final Type type, final boolean onlySymbolLiveValue) {
assert symbol != null : "No symbol to store";
if (symbol.hasSlot()) {
- final int slot = symbol.getSlot();
- debug("store symbol", symbol.getName(), " slot=", slot);
- popType(symbol.getSymbolType()).store(method, slot);
+ final boolean isLiveType = symbol.hasSlotFor(type);
+ final LocalVariableDef existingDef = localVariableDefs.get(symbol);
+ if(existingDef == null || existingDef.type != type) {
+ final jdk.internal.org.objectweb.asm.Label here = new jdk.internal.org.objectweb.asm.Label();
+ if(isLiveType) {
+ final LocalVariableDef newDef = new LocalVariableDef(here, type);
+ localVariableDefs.put(symbol, newDef);
+ }
+ method.visitLabel(here);
+ if(existingDef != null) {
+ endLocalValueDef(symbol, existingDef, here);
+ }
+ }
+ if(isLiveType) {
+ final int slot = symbol.getSlot(type);
+ debug("store symbol", symbol.getName(), " type=", type, " slot=", slot);
+ storeHidden(type, slot, onlySymbolLiveValue);
+ } else {
+ if(onlySymbolLiveValue) {
+ markDeadLocalVariable(symbol);
+ }
+ debug("dead store symbol ", symbol.getName(), " type=", type);
+ pop();
+ }
} else if (symbol.isParam()) {
assert !symbol.isScope();
assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
final int index = symbol.getFieldIndex();
if (functionNode.needsArguments()) {
+ convert(Type.OBJECT);
debug("store symbol", symbol.getName(), " arguments index=", index);
loadCompilerConstant(ARGUMENTS);
load(index);
ArgumentSetter.SET_ARGUMENT.invoke(this);
} else {
+ convert(Type.OBJECT);
// varargs without arguments object - just do array store to __varargs__
debug("store symbol", symbol.getName(), " array index=", index);
loadCompilerConstant(VARARGS);
load(index);
ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
}
+ } else {
+ debug("dead store symbol ", symbol.getName(), " type=", type);
+ pop();
}
}
/**
- * Pop a value from the stack and store it in a given local variable
- * slot.
+ * Pop a value from the stack and store it in a local variable slot. Note that in contrast with
+ * {@link #store(Symbol, Type)}, this method does not adjust the local variable table, nor marks slots for
+ * alternative value types for the symbol as being dead. For that reason, this method is usually not called
+ * directly. Notable exceptions are temporary internal locals (e.g. quick store, last-catch-condition, etc.) that
+ * are not desired to show up in the local variable table.
*
* @param type the type to pop
* @param slot the slot
*/
- void store(final Type type, final int slot) {
+ void storeHidden(final Type type, final int slot) {
+ storeHidden(type, slot, true);
+ }
+
+ void storeHidden(final Type type, final int slot, final boolean onlyLiveSymbolValue) {
+ explicitStore(type, slot);
+ stack.onLocalStore(type, slot, onlyLiveSymbolValue);
+ }
+
+ void storeTemp(final Type type, final int slot) {
+ explicitStore(type, slot);
+ defineTemporaryLocalVariable(slot, slot + type.getSlots());
+ onLocalStore(type, slot);
+ }
+
+ void onLocalStore(final Type type, final int slot) {
+ stack.onLocalStore(type, slot, true);
+ }
+
+ private void explicitStore(final Type type, final int slot) {
+ assert slot != -1;
+ debug("explicit store", type, slot);
popType(type);
type.store(method, slot);
}
/**
+ * Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value
+ * in them.
+ * @param fromSlot first slot, inclusive.
+ * @param toSlot last slot, exclusive.
+ */
+ void defineBlockLocalVariable(final int fromSlot, final int toSlot) {
+ stack.defineBlockLocalVariable(fromSlot, toSlot);
+ }
+
+ /**
+ * Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no
+ * live value in them.
+ * @param fromSlot first slot, inclusive.
+ * @param toSlot last slot, exclusive.
+ */
+ void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) {
+ stack.defineTemporaryLocalVariable(fromSlot, toSlot);
+ }
+
+ /**
+ * Defines a new temporary local variable and returns its allocated index.
+ * @param width the required width (in slots) for the new variable.
+ * @return the bytecode slot index where the newly allocated local begins.
+ */
+ int defineTemporaryLocalVariable(final int width) {
+ return stack.defineTemporaryLocalVariable(width);
+ }
+
+ void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) {
+ if(isReachable()) {
+ stack.undefineLocalVariables(fromSlot, canTruncateSymbol);
+ }
+ }
+
+ List<Type> getLocalVariableTypes() {
+ return stack.localVariableTypes;
+ }
+
+ List<Type> getWidestLiveLocals(final List<Type> localTypes) {
+ return stack.getWidestLiveLocals(localTypes);
+ }
+
+ String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) {
+ return stack.markSymbolBoundariesInLvarTypesDescriptor(lvarDescriptor);
+ }
+
+ /**
* Increment/Decrement a local integer by the given value.
*
* @param slot the int slot
@@ -999,9 +1330,9 @@ public class MethodEmitter implements Emitter {
public void athrow() {
debug("athrow");
final Type receiver = popType(Type.OBJECT);
- assert receiver.isObject();
+ assert Throwable.class.isAssignableFrom(receiver.getTypeClass()) : receiver.getTypeClass();
method.visitInsn(ATHROW);
- stack = null;
+ doesNotContinueSequentially();
}
/**
@@ -1130,11 +1461,7 @@ public class MethodEmitter implements Emitter {
popType(Type.OBJECT);
}
- if (opcode == INVOKEINTERFACE) {
- method.visitMethodInsn(opcode, className, methodName, methodDescriptor, true);
- } else {
- method.visitMethodInsn(opcode, className, methodName, methodDescriptor, false);
- }
+ method.visitMethodInsn(opcode, className, methodName, methodDescriptor, opcode == INVOKEINTERFACE);
if (returnType != null) {
pushType(returnType);
@@ -1197,7 +1524,7 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
+ MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
invokestatic(className, methodName, methodDescriptor);
popType();
pushType(returnType);
@@ -1235,8 +1562,9 @@ public class MethodEmitter implements Emitter {
*/
void lookupswitch(final Label defaultLabel, final int[] values, final Label... table) {//Collection<Label> table) {
debug("lookupswitch", peekType());
- popType(Type.INT);
+ adjustStackForSwitch(defaultLabel, table);
method.visitLookupSwitchInsn(defaultLabel.getLabel(), values, getLabels(table));
+ doesNotContinueSequentially();
}
/**
@@ -1248,8 +1576,17 @@ public class MethodEmitter implements Emitter {
*/
void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
debug("tableswitch", peekType());
- popType(Type.INT);
+ adjustStackForSwitch(defaultLabel, table);
method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
+ doesNotContinueSequentially();
+ }
+
+ private void adjustStackForSwitch(final Label defaultLabel, final Label... table) {
+ popType(Type.INT);
+ joinTo(defaultLabel);
+ for(final Label label: table) {
+ joinTo(label);
+ }
}
/**
@@ -1305,7 +1642,7 @@ public class MethodEmitter implements Emitter {
convert(type);
}
popType(type)._return(method);
- stack = null;
+ doesNotContinueSequentially();
}
/**
@@ -1322,18 +1659,7 @@ public class MethodEmitter implements Emitter {
debug("return [void]");
assert stack.isEmpty() : stack;
method.visitInsn(RETURN);
- stack = null;
- }
-
- /**
- * Goto, possibly when splitting is taking place. If
- * a splitNode exists, we need to handle the case that the
- * jump target is another method
- *
- * @param label destination label
- */
- void splitAwareGoto(final LexicalContext lc, final Label label) {
- _goto(label);
+ doesNotContinueSequentially();
}
/**
@@ -1359,7 +1685,7 @@ public class MethodEmitter implements Emitter {
assert peekType().isInteger() || peekType().isBoolean() || peekType().isObject() : "expecting integer type or object for jump, but found " + peekType();
popType();
}
- mergeStackTo(label);
+ joinTo(label);
method.visitJumpInsn(opcode, label.getLabel());
}
@@ -1454,6 +1780,16 @@ public class MethodEmitter implements Emitter {
}
/**
+ * Generate an if_icmplt
+ *
+ * @param label label to true case
+ */
+ void if_icmplt(final Label label) {
+ debug("if_icmplt", label);
+ jump(IF_ICMPLT, label, 2);
+ }
+
+ /**
* Generate an ifle
*
* @param label label to true case
@@ -1464,6 +1800,16 @@ public class MethodEmitter implements Emitter {
}
/**
+ * Generate an if_icmple
+ *
+ * @param label label to true case
+ */
+ void if_icmple(final Label label) {
+ debug("if_icmple", label);
+ jump(IF_ICMPLE, label, 2);
+ }
+
+ /**
* Generate an ifgt
*
* @param label label to true case
@@ -1474,6 +1820,16 @@ public class MethodEmitter implements Emitter {
}
/**
+ * Generate an if_icmpgt
+ *
+ * @param label label to true case
+ */
+ void if_icmpgt(final Label label) {
+ debug("if_icmpgt", label);
+ jump(IF_ICMPGT, label, 2);
+ }
+
+ /**
* Generate an ifge
*
* @param label label to true case
@@ -1484,24 +1840,58 @@ public class MethodEmitter implements Emitter {
}
/**
+ * Generate an if_icmpge
+ *
+ * @param label label to true case
+ */
+ void if_icmpge(final Label label) {
+ debug("if_icmpge", label);
+ jump(IF_ICMPGE, label, 2);
+ }
+
+ /**
* Unconditional jump to a label
*
* @param label destination label
*/
void _goto(final Label label) {
- //debug("goto", label);
+ debug("goto", label);
jump(GOTO, label, 0);
- stack = null; //whoever reaches the point after us provides the stack, because we don't
+ doesNotContinueSequentially(); //whoever reaches the point after us provides the stack, because we don't
+ }
+
+ /**
+ * Unconditional jump to the start label of a loop. It differs from ordinary {@link #_goto(Label)} in that it will
+ * preserve the current label stack, as the next instruction after the goto is loop body that the loop will come
+ * back to. Also used to jump at the start label of the continuation handler, as it behaves much like a loop test in
+ * the sense that after it is evaluated, it also jumps backwards.
+ *
+ * @param loopStart start label of a loop
+ */
+ void gotoLoopStart(final Label loopStart) {
+ debug("goto (loop)", loopStart);
+ jump(GOTO, loopStart, 0);
}
/**
- * Examine two stacks and make sure they are of the same size and their
- * contents are equivalent to each other
- * @param s0 first stack
- * @param s1 second stack
+ * Unconditional jump without any control flow and data flow testing. You should not normally use this method when
+ * generating code, except if you're very sure that you know what you're doing. Normally only used for the
+ * admittedly torturous control flow of continuation handler plumbing.
+ * @param target the target of the jump
+ */
+ void uncheckedGoto(final Label target) {
+ method.visitJumpInsn(GOTO, target.getLabel());
+ }
+
+ /**
+ * Potential transfer of control to a catch block.
*
- * @return true if stacks are equivalent, false otherwise
+ * @param catchLabel destination catch label
*/
+ void canThrow(final Label catchLabel) {
+ catchLabel.joinFromTry(stack, false);
+ }
+
/**
* A join in control flow - helper function that makes sure all entry stacks
* discovered for the join point so far are equivalent
@@ -1511,45 +1901,46 @@ public class MethodEmitter implements Emitter {
*
* @param label label
*/
- private void mergeStackTo(final Label label) {
- //sometimes we can do a merge stack without having a stack - i.e. when jumping ahead to dead code
- //see NASHORN-73. So far we had been saved by the line number nodes. This should have been fixed
- //by Lower removing everything after an unconditionally executed terminating statement OR a break
- //or continue in a block. Previously code left over after breaks and continues was still there
- //and caused bytecode to be generated - which crashed on stack not being there, as the merge
- //was not in fact preceeded by a visit. Furthermore, this led to ASM putting out its NOP NOP NOP
- //ATHROW sequences instead of no code being generated at all. This should now be fixed.
- assert stack != null : label + " entered with no stack. deadcode that remains?";
-
- final Label.Stack labelStack = label.getStack();
- if (labelStack == null) {
- label.setStack(stack.copy());
- return;
- }
- assert stack.isEquivalentTo(labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point";
+ private void joinTo(final Label label) {
+ assert isReachable();
+ label.joinFrom(stack);
}
/**
* Register a new label, enter it here.
+ * @param label
+ */
+ void label(final Label label) {
+ breakLabel(label, -1);
+ }
+
+ /**
+ * Register a new break target label, enter it here.
*
* @param label the label
+ * @param liveLocals the number of live locals at this label
*/
- void label(final Label label) {
- /*
- * If stack == null, this means that we came here not through a fallthrough.
- * E.g. a label after an athrow. Then we create a new stack if one doesn't exist
- * for this location already.
- */
- if (stack == null) {
- stack = label.getStack();
- if (stack == null) {
- newStack();
- }
+ void breakLabel(final Label label, final int liveLocals) {
+ if (!isReachable()) {
+ // If we emit a label, and the label's stack is null, it must not be reachable.
+ assert (label.getStack() == null) != label.isReachable();
+ } else {
+ joinTo(label);
+ }
+ // Use label's stack as we might have no stack.
+ final Label.Stack labelStack = label.getStack();
+ stack = labelStack == null ? null : labelStack.clone();
+ if(stack != null && label.isBreakTarget() && liveLocals != -1) {
+ // This has to be done because we might not have another frame to provide us with its firstTemp if the label
+ // is only reachable through a break or continue statement; also in this case, the frame can actually
+ // give us a higher number of live locals, e.g. if it comes from a catch. Typical example:
+ // for(;;) { try{ throw 0; } catch(e) { break; } }.
+ // Since the for loop can only be exited through the break in the catch block, it'll bring with it the
+ // "e" as a live local, and we need to trim it off here.
+ assert stack.firstTemp >= liveLocals;
+ stack.firstTemp = liveLocals;
}
debug_label(label);
-
- mergeStackTo(label); //we have to merge our stack to whatever is in the label
-
method.visitLabel(label.getLabel());
}
@@ -1561,13 +1952,32 @@ public class MethodEmitter implements Emitter {
* @return the method emitter
*/
MethodEmitter convert(final Type to) {
- final Type type = peekType().convert(method, to);
+ final Type from = peekType();
+ final Type type = from.convert(method, to);
if (type != null) {
- if (!peekType().isEquivalentTo(to)) {
- debug("convert", peekType(), "->", to);
+ if (!from.isEquivalentTo(to)) {
+ debug("convert", from, "->", to);
+ }
+ if (type != from) {
+ final int l0 = stack.getTopLocalLoad();
+ popType();
+ pushType(type);
+ // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
+ // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
+ // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
+ // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
+ // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
+ // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
+ // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
+ // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
+ // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
+ // NOTE: as a more general observation, we could theoretically track the operations required to
+ // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
+ // We won't go there in the current system
+ if(!from.isObject()) {
+ stack.markLocalLoad(l0);
+ }
}
- popType();
- pushType(type);
}
return this;
}
@@ -1590,8 +2000,8 @@ public class MethodEmitter implements Emitter {
* @return common type
*/
private BitwiseType get2i() {
- final BitwiseType p0 = popInteger();
- final BitwiseType p1 = popInteger();
+ final BitwiseType p0 = popBitwise();
+ final BitwiseType p1 = popBitwise();
assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
return p0;
}
@@ -1613,9 +2023,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter add() {
+ MethodEmitter add(final int programPoint) {
debug("add");
- pushType(get2().add(method));
+ pushType(get2().add(method, programPoint));
return this;
}
@@ -1624,9 +2034,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter sub() {
+ MethodEmitter sub(final int programPoint) {
debug("sub");
- pushType(get2n().sub(method));
+ pushType(get2n().sub(method, programPoint));
return this;
}
@@ -1635,9 +2045,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter mul() {
+ MethodEmitter mul(final int programPoint) {
debug("mul ");
- pushType(get2n().mul(method));
+ pushType(get2n().mul(method, programPoint));
return this;
}
@@ -1646,9 +2056,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter div() {
+ MethodEmitter div(final int programPoint) {
debug("div");
- pushType(get2n().div(method));
+ pushType(get2n().div(method, programPoint));
return this;
}
@@ -1657,9 +2067,9 @@ public class MethodEmitter implements Emitter {
*
* @return the method emitter
*/
- MethodEmitter rem() {
+ MethodEmitter rem(final int programPoint) {
debug("rem");
- pushType(get2n().rem(method));
+ pushType(get2n().rem(method, programPoint));
return this;
}
@@ -1670,13 +2080,23 @@ public class MethodEmitter implements Emitter {
* @return array of Types
*/
protected Type[] getTypesFromStack(final int count) {
- final Type[] types = new Type[count];
- int pos = 0;
- for (int i = count - 1; i >= 0; i--) {
- types[i] = stack.peek(pos++);
- }
+ return stack.getTopTypes(count);
+ }
+
+ int[] getLocalLoadsOnStack(final int from, final int to) {
+ return stack.getLocalLoads(from, to);
+ }
- return types;
+ int getStackSize() {
+ return stack.size();
+ }
+
+ int getFirstTemp() {
+ return stack.firstTemp;
+ }
+
+ int getUsedSlotsWithLiveTemporaries() {
+ return stack.getUsedSlotsWithLiveTemporaries();
}
/**
@@ -1693,7 +2113,14 @@ public class MethodEmitter implements Emitter {
int pos = 0;
for (int i = argCount - 1; i >= 0; i--) {
- paramTypes[i] = stack.peek(pos++);
+ Type pt = stack.peek(pos++);
+ // "erase" specific ScriptObject subtype info - except for NativeArray.
+ // NativeArray is used for array/List/Deque conversion for Java calls.
+ if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) &&
+ !NativeArray.class.isAssignableFrom(pt.getTypeClass())) {
+ pt = Type.SCRIPT_OBJECT;
+ }
+ paramTypes[i] = pt;
}
final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
for (int i = 0; i < argCount; i++) {
@@ -1703,6 +2130,20 @@ public class MethodEmitter implements Emitter {
return descriptor;
}
+ MethodEmitter invalidateSpecialName(final String name) {
+ switch (name) {
+ case "apply":
+ case "call":
+ debug("invalidate_name", "name=", name);
+ load("Function");
+ invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME);
+ break;
+ default:
+ break;
+ }
+ return this;
+ }
+
/**
* Generate a dynamic new
*
@@ -1712,6 +2153,7 @@ public class MethodEmitter implements Emitter {
* @return the method emitter
*/
MethodEmitter dynamicNew(final int argCount, final int flags) {
+ assert !isOptimistic(flags);
debug("dynamic_new", "argcount=", argCount);
final String signature = getDynamicSignature(Type.OBJECT, argCount);
method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
@@ -1738,6 +2180,14 @@ public class MethodEmitter implements Emitter {
return this;
}
+ MethodEmitter dynamicArrayPopulatorCall(final int argCount, final int startIndex) {
+ debug("populate_array", "args=", argCount, "startIndex=", startIndex);
+ final String signature = getDynamicSignature(Type.OBJECT_ARRAY, argCount);
+ method.visitInvokeDynamicInsn("populateArray", signature, POPULATE_ARRAY_BOOTSTRAP, startIndex);
+ pushType(Type.OBJECT_ARRAY);
+ return this;
+ }
+
/**
* Generate a dynamic call for a runtime node
*
@@ -1764,11 +2214,11 @@ public class MethodEmitter implements Emitter {
* @param name name of property
* @param flags call site flags
* @param isMethod should it prefer retrieving methods
- *
+ * @param isIndex is this an index operation?
* @return the method emitter
*/
- MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
- debug("dynamic_get", name, valueType);
+ MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod, final boolean isIndex) {
+ debug("dynamic_get", name, valueType, getProgramPoint(flags));
Type type = valueType;
if (type.isObject() || type.isBoolean()) {
@@ -1776,11 +2226,10 @@ public class MethodEmitter implements Emitter {
}
popType(Type.SCOPE);
- method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
- NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
+ method.visitInvokeDynamicInsn(dynGetOperation(isMethod, isIndex) + ':' + NameCodec.encode(name),
+ Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
pushType(type);
-
convert(valueType); //most probably a nop
return this;
@@ -1789,12 +2238,13 @@ public class MethodEmitter implements Emitter {
/**
* Generate dynamic setter. Pop receiver and property from stack.
*
- * @param valueType the type of the value to set
- * @param name name of property
- * @param flags call site flags
+ * @param name name of property
+ * @param flags call site flags
+ * @param isIndex is this an index operation?
*/
- void dynamicSet(final String name, final int flags) {
- debug("dynamic_set", name, peekType());
+ void dynamicSet(final String name, final int flags, final boolean isIndex) {
+ assert !isOptimistic(flags);
+ debug("dynamic_set", name, peekType());
Type type = peekType();
if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
@@ -1804,7 +2254,8 @@ public class MethodEmitter implements Emitter {
popType(type);
popType(Type.SCOPE);
- method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
+ method.visitInvokeDynamicInsn(dynSetOperation(isIndex) + ':' + NameCodec.encode(name),
+ methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
}
/**
@@ -1818,7 +2269,8 @@ public class MethodEmitter implements Emitter {
* @return the method emitter
*/
MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
- debug("dynamic_get_index", peekType(1), "[", peekType(), "]");
+ assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class;
+ debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
Type resultType = result;
if (result.isBoolean()) {
@@ -1836,8 +2288,7 @@ public class MethodEmitter implements Emitter {
final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
- method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod",
- signature, LINKERBOOTSTRAP, flags);
+ method.visitInvokeDynamicInsn(dynGetOperation(isMethod, true), signature, LINKERBOOTSTRAP, flags);
pushType(resultType);
if (result.isBoolean()) {
@@ -1847,6 +2298,13 @@ public class MethodEmitter implements Emitter {
return this;
}
+ private static String getProgramPoint(final int flags) {
+ if((flags & CALLSITE_OPTIMISTIC) == 0) {
+ return "";
+ }
+ return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT);
+ }
+
/**
* Dynamic setter for indexed structures. Pop value, index and receiver from
* stack, generate appropriate signature based on types
@@ -1854,6 +2312,7 @@ public class MethodEmitter implements Emitter {
* @param flags call site flags for setter
*/
void dynamicSetIndex(final int flags) {
+ assert !isOptimistic(flags);
debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType());
Type value = peekType();
@@ -2009,10 +2468,9 @@ public class MethodEmitter implements Emitter {
* Register line number at a label
*
* @param line line number
- * @param label label
*/
void lineNumber(final int line) {
- if (env._debug_lines) {
+ if (context.getEnv()._debug_lines) {
debug_label("[LINE]", line);
final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label();
method.visitLabel(l);
@@ -2020,6 +2478,56 @@ public class MethodEmitter implements Emitter {
}
}
+ void beforeJoinPoint(final JoinPredecessor joinPredecessor) {
+ LocalVariableConversion next = joinPredecessor.getLocalVariableConversion();
+ while(next != null) {
+ final Symbol symbol = next.getSymbol();
+ if(next.isLive()) {
+ emitLocalVariableConversion(next, true);
+ } else {
+ markDeadLocalVariable(symbol);
+ }
+ next = next.getNext();
+ }
+ }
+
+ void beforeTry(final TryNode tryNode, final Label recovery) {
+ LocalVariableConversion next = tryNode.getLocalVariableConversion();
+ while(next != null) {
+ if(next.isLive()) {
+ final Type to = emitLocalVariableConversion(next, false);
+ recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true);
+ }
+ next = next.getNext();
+ }
+ }
+
+ private static String dynGetOperation(final boolean isMethod, final boolean isIndex) {
+ if (isMethod) {
+ return isIndex ? "dyn:getMethod|getElem|getProp" : "dyn:getMethod|getProp|getElem";
+ } else {
+ return isIndex ? "dyn:getElem|getProp|getMethod" : "dyn:getProp|getElem|getMethod";
+ }
+ }
+
+ private static String dynSetOperation(final boolean isIndex) {
+ return isIndex ? "dyn:setElem|setProp" : "dyn:setProp|setElem";
+ }
+
+ private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
+ final Type from = conversion.getFrom();
+ final Type to = conversion.getTo();
+ final Symbol symbol = conversion.getSymbol();
+ assert symbol.isBytecodeLocal();
+ if(from == Type.UNDEFINED) {
+ loadUndefined(to);
+ } else {
+ load(symbol, from).convert(to);
+ }
+ store(symbol, to, onlySymbolLiveValue);
+ return to;
+ }
+
/*
* Debugging below
*/
@@ -2086,12 +2594,55 @@ public class MethodEmitter implements Emitter {
*
* @param args debug information to print
*/
+ @SuppressWarnings("unused")
private void debug(final Object... args) {
- if (DEBUG) {
+ if (debug) {
debug(30, args);
}
}
+ private void debug(final String arg) {
+ if (debug) {
+ debug(30, arg);
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1 });
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1, final Object arg2) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1, arg2 });
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1, arg2, arg3 });
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 });
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 });
+ }
+ }
+
+ private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) {
+ if (debug) {
+ debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 });
+ }
+ }
+
/**
* Debug function that outputs generated bytecode and stack contents
* for a label - indentation is currently the only thing that differs
@@ -2099,13 +2650,13 @@ public class MethodEmitter implements Emitter {
* @param args debug information to print
*/
private void debug_label(final Object... args) {
- if (DEBUG) {
+ if (debug) {
debug(22, args);
}
}
private void debug(final int padConstant, final Object... args) {
- if (DEBUG) {
+ if (debug) {
final StringBuilder sb = new StringBuilder();
int pad;
@@ -2118,7 +2669,7 @@ public class MethodEmitter implements Emitter {
pad--;
}
- if (stack != null && !stack.isEmpty()) {
+ if (isReachable() && !stack.isEmpty()) {
sb.append("{");
sb.append(stack.size());
sb.append(":");
@@ -2148,7 +2699,10 @@ public class MethodEmitter implements Emitter {
} else {
sb.append(t.getDescriptor());
}
-
+ final int loadIndex = stack.localLoads[stack.sp - 1 - pos];
+ if(loadIndex != Label.Stack.NON_LOAD) {
+ sb.append('(').append(loadIndex).append(')');
+ }
if (pos + 1 < stack.size()) {
sb.append(' ');
}
@@ -2168,10 +2722,10 @@ public class MethodEmitter implements Emitter {
sb.append(' ');
}
- if (env != null) { //early bootstrap code doesn't have inited context yet
- LOG.info(sb);
+ if (context.getEnv() != null) { //early bootstrap code doesn't have inited context yet
+ log.info(sb);
if (DEBUG_TRACE_LINE == linePrefix) {
- new Throwable().printStackTrace(LOG.getOutputStream());
+ new Throwable().printStackTrace(log.getOutputStream());
}
}
}
@@ -2189,8 +2743,17 @@ public class MethodEmitter implements Emitter {
return hasReturn;
}
- List<Label> getExternalTargets() {
- return null;
+ /**
+ * Invoke to enforce assertions preventing load from a local variable slot that's known to not have been written to.
+ * Used by CodeGenerator, as it strictly enforces tracking of stores. Simpler uses of MethodEmitter, e.g. those
+ * for creating initializers for structure classes, array getters, etc. don't have strict tracking of stores,
+ * therefore they would fail if they had this assertion turned on.
+ */
+ void setPreventUndefinedLoad() {
+ this.preventUndefinedLoad = true;
}
+ private static boolean isOptimistic(final int flags) {
+ return (flags & CALLSITE_OPTIMISTIC) != 0;
+ }
}
diff --git a/src/jdk/nashorn/internal/codegen/Namespace.java b/src/jdk/nashorn/internal/codegen/Namespace.java
index 72f77a5b..5c5115a9 100644
--- a/src/jdk/nashorn/internal/codegen/Namespace.java
+++ b/src/jdk/nashorn/internal/codegen/Namespace.java
@@ -80,7 +80,6 @@ public class Namespace {
if (counter != null) {
final int count = counter + 1;
namespaceDirectory.put(base, count);
-
return base + '-' + count;
}
}
diff --git a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
index 21cc3c5e..a5a5cf6f 100644
--- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
@@ -35,12 +35,20 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.className;
import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT;
+import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_DOUBLE_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_INT_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_LONG_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_UNDEFINED_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedList;
@@ -49,24 +57,35 @@ import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.FunctionScope;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
import jdk.nashorn.internal.runtime.options.Options;
/**
* Generates the ScriptObject subclass structure with fields for a user objects.
*/
-public final class ObjectClassGenerator {
+@Logger(name="fields")
+public final class ObjectClassGenerator implements Loggable {
/**
- * Marker for scope parameters.
+ * Type guard to make sure we don't unnecessarily explode field storages. Rather unbox e.g.
+ * a java.lang.Number than blow up the field. Gradually, optimistic types should create almost
+ * no boxed types
*/
- static final String SCOPE_MARKER = "P";
+ private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class);
+
+ /**
+ * Marker for scope parameters
+ */
+ private static final String SCOPE_MARKER = "P";
/**
* Minimum number of extra fields in an object.
@@ -77,29 +96,26 @@ public final class ObjectClassGenerator {
* Debug field logger
* Should we print debugging information for fields when they are generated and getters/setters are called?
*/
- public static final DebugLogger LOG = new DebugLogger("fields", "nashorn.fields.debug");
-
- /**
- * is field debugging enabled. Several modules in codegen and properties use this, hence
- * public access.
- */
- public static final boolean DEBUG_FIELDS = LOG.isEnabled();
+ private final DebugLogger log;
/**
* Should the runtime only use java.lang.Object slots for fields? If this is false, the representation
* will be a primitive 64-bit long value used for all primitives and a java.lang.Object for references.
* This introduces a larger number of method handles in the system, as we need to have different getters
- * and setters for the different fields. Currently this introduces significant overhead in Hotspot.
+ * and setters for the different fields.
*
* This is engineered to plug into the TaggedArray implementation, when it's done.
*/
- public static final boolean OBJECT_FIELDS_ONLY = !Options.getBooleanProperty("nashorn.fields.dual");
+ public static final boolean OBJECT_FIELDS_ONLY = Options.getBooleanProperty("nashorn.fields.objects");
/** The field types in the system */
private static final List<Type> FIELD_TYPES = new LinkedList<>();
/** What type is the primitive type in dual representation */
- public static final Type PRIMITIVE_TYPE = Type.LONG;
+ public static final Type PRIMITIVE_FIELD_TYPE = Type.LONG;
+
+ private static final MethodHandle GET_DIFFERENT = findOwnMH("getDifferent", Object.class, Object.class, Class.class, MethodHandle.class, MethodHandle.class, int.class);
+ private static final MethodHandle GET_DIFFERENT_UNDEFINED = findOwnMH("getDifferentUndefined", Object.class, int.class);
/**
* The list of field types that we support - one type creates one field. This is currently either
@@ -107,33 +123,16 @@ public final class ObjectClassGenerator {
*/
static {
if (!OBJECT_FIELDS_ONLY) {
- System.err.println("WARNING!!! Running with primitive fields - there is untested functionality!");
- FIELD_TYPES.add(PRIMITIVE_TYPE);
+ FIELD_TYPES.add(PRIMITIVE_FIELD_TYPE);
}
FIELD_TYPES.add(Type.OBJECT);
}
+ private static boolean initialized = false;
/** The context */
private final Context context;
/**
- * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
- * in the dual--fields world
- */
- public static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
- Arrays.asList(
- Type.INT,
- Type.LONG,
- Type.NUMBER,
- Type.OBJECT));
-
- //these are hard coded for speed and so that we can switch on them
- private static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class);
- private static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class);
- private static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class);
- private static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class);
-
- /**
* Constructor
*
* @param context a context
@@ -141,64 +140,39 @@ public final class ObjectClassGenerator {
public ObjectClassGenerator(final Context context) {
this.context = context;
assert context != null;
+ this.log = initLogger(context);
+ if (!initialized) {
+ initialized = true;
+ if (OBJECT_FIELDS_ONLY) {
+ log.warning("Running with object fields only - this is a deprecated configuration.");
+ }
+ }
}
- /**
- * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes())
- *
- * @param type the type
- *
- * @return the accessor index, or -1 if no accessor of this type exists
- */
- public static int getAccessorTypeIndex(final Type type) {
- return getAccessorTypeIndex(type.getTypeClass());
- }
-
- /**
- * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes())
- *
- * Note that this is hardcoded with respect to the dynamic contents of the accessor
- * types array for speed. Hotspot got stuck with this as 5% of the runtime in
- * a benchmark when it looped over values and increased an index counter. :-(
- *
- * @param type the type
- *
- * @return the accessor index, or -1 if no accessor of this type exists
- */
- public static int getAccessorTypeIndex(final Class<?> type) {
- if (type == int.class) {
- return 0;
- } else if (type == long.class) {
- return 1;
- } else if (type == double.class) {
- return 2;
- } else if (!type.isPrimitive()) {
- return 3;
- }
- return -1;
+ @Override
+ public DebugLogger getLogger() {
+ return log;
}
- /**
- * Return the number of accessor types available.
- *
- * @return number of accessor types in system
- */
- public static int getNumberOfAccessorTypes() {
- return ACCESSOR_TYPES.size();
+ @Override
+ public DebugLogger initLogger(final Context ctxt) {
+ return ctxt.getLogger(this.getClass());
}
/**
- * Return the accessor type based on its index in [0..getNumberOfAccessorTypes())
- * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always
- * go to a type of higher index
- *
- * @param index accessor type index
- *
- * @return a type corresponding to the index.
+ * Pack a number into a primitive long field
+ * @param n number object
+ * @return primitive long value with all the bits in the number
*/
-
- public static Type getAccessorType(final int index) {
- return ACCESSOR_TYPES.get(index);
+ public static long pack(final Number n) {
+ if (n instanceof Integer) {
+ return n.intValue();
+ } else if (n instanceof Long) {
+ return n.longValue();
+ } else if (n instanceof Double) {
+ return Double.doubleToRawLongBits(n.doubleValue());
+ }
+ throw new AssertionError("cannot pack" + n);
}
/**
@@ -232,10 +206,10 @@ public final class ObjectClassGenerator {
* @param clazz the JavaScript scope class.
* @return the number of fields in the scope class.
*/
- public static int getFieldCount(Class<?> clazz) {
+ public static int getFieldCount(final Class<?> clazz) {
final String name = clazz.getSimpleName();
final String prefix = JS_OBJECT_PREFIX.symbolName();
- if(prefix.equals(name)) {
+ if (prefix.equals(name)) {
return 0;
}
final int scopeMarker = name.indexOf(SCOPE_MARKER);
@@ -264,13 +238,16 @@ public final class ObjectClassGenerator {
* @param fieldNames fields to initialize to undefined, where applicable
*/
private static void initializeToUndefined(final MethodEmitter init, final String className, final List<String> fieldNames) {
+ if (!OBJECT_FIELDS_ONLY) {
+ // no need to initialize anything to undefined in the dual field world
+ // - then we have a constant getter for undefined for any unknown type
+ return;
+ }
+
if (fieldNames.isEmpty()) {
return;
}
- // always initialize fields to undefined, even with --dual-fields. Then it's ok to
- // remember things like "widest set type" in properties, and if it's object, don't
- // add any special "return undefined" getters, saving an invalidation
init.load(Type.OBJECT, JAVA_THIS.slot());
init.loadUndefined(Type.OBJECT);
@@ -324,10 +301,14 @@ public final class ObjectClassGenerator {
init.returnVoid();
init.end();
- newEmptyInit(classEmitter, className);
- newAllocate(classEmitter, className);
+ final MethodEmitter initWithSpillArrays = newInitWithSpillArraysMethod(classEmitter, ScriptObject.class);
+ initWithSpillArrays.returnVoid();
+ initWithSpillArrays.end();
- return toByteArray(classEmitter);
+ newEmptyInit(className, classEmitter);
+ newAllocate(className, classEmitter);
+
+ return toByteArray(className, classEmitter);
}
/**
@@ -340,8 +321,8 @@ public final class ObjectClassGenerator {
* @return Byte codes for generated class.
*/
public byte[] generate(final int fieldCount, final int paramCount) {
- final String className = getClassName(fieldCount, paramCount);
- final String superName = className(FunctionScope.class);
+ final String className = getClassName(fieldCount, paramCount);
+ final String superName = className(FunctionScope.class);
final ClassEmitter classEmitter = newClassEmitter(className, superName);
final List<String> initFields = addFields(classEmitter, fieldCount);
@@ -350,12 +331,17 @@ public final class ObjectClassGenerator {
init.returnVoid();
init.end();
+ final MethodEmitter initWithSpillArrays = newInitWithSpillArraysMethod(classEmitter, FunctionScope.class);
+ initializeToUndefined(initWithSpillArrays, className, initFields);
+ initWithSpillArrays.returnVoid();
+ initWithSpillArrays.end();
+
final MethodEmitter initWithArguments = newInitScopeWithArgumentsMethod(classEmitter);
initializeToUndefined(initWithArguments, className, initFields);
initWithArguments.returnVoid();
initWithArguments.end();
- return toByteArray(classEmitter);
+ return toByteArray(className, classEmitter);
}
/**
@@ -391,7 +377,7 @@ public final class ObjectClassGenerator {
* @return Open class emitter.
*/
private ClassEmitter newClassEmitter(final String className, final String superName) {
- final ClassEmitter classEmitter = new ClassEmitter(context.getEnv(), className, superName);
+ final ClassEmitter classEmitter = new ClassEmitter(context, className, superName);
classEmitter.begin();
return classEmitter;
@@ -414,6 +400,18 @@ public final class ObjectClassGenerator {
return init;
}
+ private static MethodEmitter newInitWithSpillArraysMethod(final ClassEmitter classEmitter, final Class<?> superClass) {
+ final MethodEmitter init = classEmitter.init(PropertyMap.class, long[].class, Object[].class);
+ init.begin();
+ init.load(Type.OBJECT, JAVA_THIS.slot());
+ init.load(Type.OBJECT, INIT_MAP.slot());
+ init.load(Type.LONG_ARRAY, 2);
+ init.load(Type.OBJECT_ARRAY, 3);
+ init.invoke(constructorNoLookup(superClass, PropertyMap.class, long[].class, Object[].class));
+
+ return init;
+ }
+
/**
* Allocate and initialize a new <init> method for scopes.
* @param classEmitter Open class emitter.
@@ -453,7 +451,7 @@ public final class ObjectClassGenerator {
* @param classEmitter Open class emitter.
* @param className Name of JavaScript class.
*/
- private static void newEmptyInit(final ClassEmitter classEmitter, final String className) {
+ private static void newEmptyInit(final String className, final ClassEmitter classEmitter) {
final MethodEmitter emptyInit = classEmitter.init();
emptyInit.begin();
emptyInit.load(Type.OBJECT, JAVA_THIS.slot());
@@ -469,10 +467,10 @@ public final class ObjectClassGenerator {
* @param classEmitter Open class emitter.
* @param className Name of JavaScript class.
*/
- private static void newAllocate(final ClassEmitter classEmitter, final String className) {
+ private static void newAllocate(final String className, final ClassEmitter classEmitter) {
final MethodEmitter allocate = classEmitter.method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), ALLOCATE.symbolName(), ScriptObject.class, PropertyMap.class);
allocate.begin();
- allocate._new(className);
+ allocate._new(className, Type.typeFor(ScriptObject.class));
allocate.dup();
allocate.load(Type.typeFor(PropertyMap.class), 0);
allocate.invoke(constructorNoLookup(className, PropertyMap.class));
@@ -486,15 +484,13 @@ public final class ObjectClassGenerator {
* @param classEmitter Open class emitter.
* @return Byte codes for the class.
*/
- private byte[] toByteArray(final ClassEmitter classEmitter) {
+ private byte[] toByteArray(final String className, final ClassEmitter classEmitter) {
classEmitter.end();
final byte[] code = classEmitter.toByteArray();
final ScriptEnvironment env = context.getEnv();
- if (env._print_code) {
- env.getErr().println(ClassEmitter.disassemble(code));
- }
+ DumpBytecode.dumpBytecode(env, log, code, className);
if (env._verify_code) {
context.verify(code);
@@ -504,20 +500,174 @@ public final class ObjectClassGenerator {
}
/** Double to long bits, used with --dual-fields for primitive double values */
- private static final MethodHandle PACK_DOUBLE =
+ public static final MethodHandle PACK_DOUBLE =
MH.explicitCastArguments(MH.findStatic(MethodHandles.publicLookup(), Double.class, "doubleToRawLongBits", MH.type(long.class, double.class)), MH.type(long.class, double.class));
/** double bits to long, used with --dual-fields for primitive double values */
- private static MethodHandle UNPACK_DOUBLE =
+ public static final MethodHandle UNPACK_DOUBLE =
MH.findStatic(MethodHandles.publicLookup(), Double.class, "longBitsToDouble", MH.type(double.class, long.class));
- /** object conversion quickies with JS semantics - used for return value and parameter filter */
- private static MethodHandle[] CONVERT_OBJECT = {
- JSType.TO_INT32.methodHandle(),
- JSType.TO_UINT32.methodHandle(),
- JSType.TO_NUMBER.methodHandle(),
- null
- };
+ //type != forType, so use the correct getter for forType, box it and throw
+ @SuppressWarnings("unused")
+ private static Object getDifferent(final Object receiver, final Class<?> forType, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final int programPoint) {
+ //create the sametype getter, and upcast to value. no matter what the store format is,
+ //
+ final MethodHandle sameTypeGetter = getterForType(forType, primitiveGetter, objectGetter);
+ final MethodHandle mh = MH.asType(sameTypeGetter, sameTypeGetter.type().changeReturnType(Object.class));
+ try {
+ final Object value = mh.invokeExact(receiver);
+ throw new UnwarrantedOptimismException(value, programPoint);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static Object getDifferentUndefined(final int programPoint) {
+ throw new UnwarrantedOptimismException(Undefined.getUndefined(), programPoint);
+ }
+
+ private static MethodHandle getterForType(final Class<?> forType, final MethodHandle primitiveGetter, final MethodHandle objectGetter) {
+ switch (getAccessorTypeIndex(forType)) {
+ case TYPE_INT_INDEX:
+ assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+ return MH.explicitCastArguments(primitiveGetter, primitiveGetter.type().changeReturnType(int.class));
+ case TYPE_LONG_INDEX:
+ assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+ return primitiveGetter;
+ case TYPE_DOUBLE_INDEX:
+ assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+ return MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE);
+ case TYPE_OBJECT_INDEX:
+ return objectGetter;
+ default:
+ throw new AssertionError(forType);
+ }
+ }
+
+ //no optimism here. we do unconditional conversion to types
+ private static MethodHandle createGetterInner(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final List<MethodHandle> converters, final int programPoint) {
+ final int fti = forType == null ? TYPE_UNDEFINED_INDEX : getAccessorTypeIndex(forType);
+ final int ti = getAccessorTypeIndex(type);
+ //this means fail if forType != type
+ final boolean isOptimistic = converters == CONVERT_OBJECT_OPTIMISTIC;
+ final boolean isPrimitiveStorage = forType != null && forType.isPrimitive();
+
+ //which is the primordial getter
+ final MethodHandle getter = OBJECT_FIELDS_ONLY ? objectGetter : isPrimitiveStorage ? primitiveGetter : objectGetter;
+
+ if (forType == null) {
+ if (isOptimistic) {
+ //return undefined if asking for object. otherwise throw UnwarrantedOptimismException
+ if (ti == TYPE_OBJECT_INDEX) {
+ return MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class);
+ }
+ //throw exception
+ return MH.asType(
+ MH.dropArguments(
+ MH.insertArguments(
+ GET_DIFFERENT_UNDEFINED,
+ 0,
+ programPoint),
+ 0,
+ Object.class),
+ getter.type().changeReturnType(type));
+ }
+ //return an undefined and coerce it to the appropriate type
+ return MH.dropArguments(GET_UNDEFINED.get(ti), 0, Object.class);
+ }
+
+ assert forType != null;
+ assert !OBJECT_FIELDS_ONLY || forType == Object.class : forType;
+
+ if (isOptimistic) {
+ if (fti < ti) {
+ //asking for a wider type than currently stored. then it's OK to coerce.
+ //e.g. stored as int, ask for long or double
+ //e.g. stored as long, ask for double
+ assert fti != TYPE_UNDEFINED_INDEX;
+ final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter);
+ return MH.asType(tgetter, tgetter.type().changeReturnType(type));
+ } else if (fti == ti) {
+ //Fast path, never throw exception - exact getter, just unpack if needed
+ return getterForType(forType, primitiveGetter, objectGetter);
+ } else {
+ assert fti > ti;
+ //if asking for a narrower type than the storage - throw exception
+ //unless FTI is object, in that case we have to go through the converters
+ //there is no
+ if (fti == TYPE_OBJECT_INDEX) {
+ return MH.filterReturnValue(
+ objectGetter,
+ MH.insertArguments(
+ converters.get(ti),
+ 1,
+ programPoint));
+ }
+
+ //asking for narrower primitive than we have stored, that is an
+ //UnwarrantedOptimismException
+ return MH.asType(
+ MH.filterArguments(
+ objectGetter,
+ 0,
+ MH.insertArguments(
+ GET_DIFFERENT,
+ 1,
+ forType,
+ primitiveGetter,
+ objectGetter,
+ programPoint)),
+ objectGetter.type().changeReturnType(type));
+ }
+ }
+
+ assert !isOptimistic;
+ //freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b
+ final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter);
+ if (fti == TYPE_OBJECT_INDEX) {
+ if (fti != ti) {
+ return MH.filterReturnValue(tgetter, CONVERT_OBJECT.get(ti));
+ }
+ return tgetter;
+ }
+
+ assert !OBJECT_FIELDS_ONLY;
+ //final MethodType pmt = primitiveGetter.type();
+ assert primitiveGetter != null;
+ final MethodType tgetterType = tgetter.type();
+ switch (fti) {
+ case TYPE_INT_INDEX: {
+ return MH.asType(tgetter, tgetterType.changeReturnType(type));
+ }
+ case TYPE_LONG_INDEX:
+ switch (ti) {
+ case TYPE_INT_INDEX:
+ //get int while an int, truncating cast of long value
+ return MH.filterReturnValue(tgetter, JSType.TO_INT32_L.methodHandle);
+ case TYPE_LONG_INDEX:
+ return primitiveGetter;
+ default:
+ return MH.asType(tgetter, tgetterType.changeReturnType(type));
+ }
+ case TYPE_DOUBLE_INDEX:
+ switch (ti) {
+ case TYPE_INT_INDEX:
+ return MH.filterReturnValue(tgetter, JSType.TO_INT32_D.methodHandle);
+ case TYPE_LONG_INDEX:
+ return MH.explicitCastArguments(tgetter, tgetterType.changeReturnType(type));
+ case TYPE_DOUBLE_INDEX:
+ assert tgetterType.returnType() == double.class;
+ return tgetter;
+ default:
+ return MH.asType(tgetter, tgetterType.changeReturnType(Object.class));
+ }
+ default:
+ throw new UnsupportedOperationException(forType + "=>" + type);
+ }
+ }
/**
* Given a primitiveGetter (optional for non dual fields) and an objectSetter that retrieve
@@ -526,7 +676,7 @@ public final class ObjectClassGenerator {
* and we want an Object getter, in the dual fields world we'd pick the primitiveGetter,
* which reads a long, use longBitsToDouble on the result to unpack it, and then change the
* return type to Object, boxing it. In the objects only world there are only object fields,
- * primtives are boxed when asked for them and we don't need to bother with primitive encoding
+ * primitives are boxed when asked for them and we don't need to bother with primitive encoding
* (or even undefined, which if forType==null) representation, so we just return whatever is
* in the object field. The object field is always initiated to Undefined, so here, where we have
* the representation for Undefined in all our bits, this is not a problem.
@@ -543,62 +693,77 @@ public final class ObjectClassGenerator {
* @param type type to retrieve it as
* @param primitiveGetter getter to read the primitive version of this field (null if Objects Only)
* @param objectGetter getter to read the object version of this field
+ * @param programPoint program point for getter, if program point is INVALID_PROGRAM_POINT, then this is not an optimistic getter
*
* @return getter for the given representation that returns the given type
*/
- public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter) {
- final int fti = forType == null ? -1 : getAccessorTypeIndex(forType);
+ public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final int programPoint) {
+ return createGetterInner(
+ forType,
+ type,
+ primitiveGetter,
+ objectGetter,
+ isValid(programPoint) ? CONVERT_OBJECT_OPTIMISTIC : CONVERT_OBJECT,
+ programPoint);
+ }
+
+ /**
+ * This is similar to the {@link ObjectClassGenerator#createGetter} function. Performs
+ * the necessary operations to massage a setter operand of type {@code type} to
+ * fit into the primitive field (if primitive and dual fields is enabled) or into
+ * the object field (box if primitive and dual fields is disabled)
+ *
+ * @param forType representation of the underlying object
+ * @param type representation of field to write, and setter signature
+ * @param primitiveSetter setter that writes to the primitive field (null if Objects Only)
+ * @param objectSetter setter that writes to the object field
+ *
+ * @return the setter for the given representation that takes a {@code type}
+ */
+ public static MethodHandle createSetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveSetter, final MethodHandle objectSetter) {
+ assert forType != null;
+
+ final int fti = getAccessorTypeIndex(forType);
final int ti = getAccessorTypeIndex(type);
if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) {
if (ti == TYPE_OBJECT_INDEX) {
- return objectGetter;
+ return objectSetter;
}
- return MH.filterReturnValue(objectGetter, CONVERT_OBJECT[ti]);
+ return MH.asType(objectSetter, objectSetter.type().changeParameterType(1, type));
}
assert !OBJECT_FIELDS_ONLY;
- if (forType == null) {
- return GET_UNDEFINED[ti];
- }
- final MethodType pmt = primitiveGetter.type();
+ final MethodType pmt = primitiveSetter.type();
switch (fti) {
case TYPE_INT_INDEX:
case TYPE_LONG_INDEX:
switch (ti) {
case TYPE_INT_INDEX:
- //get int while an int, truncating cast of long value
- return MH.explicitCastArguments(primitiveGetter, pmt.changeReturnType(int.class));
+ return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class));
case TYPE_LONG_INDEX:
- return primitiveGetter;
+ return primitiveSetter;
+ case TYPE_DOUBLE_INDEX:
+ return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE);
default:
- return MH.asType(primitiveGetter, pmt.changeReturnType(type));
+ return objectSetter;
}
case TYPE_DOUBLE_INDEX:
- final MethodHandle getPrimitiveAsDouble = MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE);
- switch (ti) {
- case TYPE_INT_INDEX:
- case TYPE_LONG_INDEX:
- return MH.explicitCastArguments(getPrimitiveAsDouble, pmt.changeReturnType(type));
- case TYPE_DOUBLE_INDEX:
- return getPrimitiveAsDouble;
- default:
- return MH.asType(getPrimitiveAsDouble, pmt.changeReturnType(Object.class));
+ if (ti == TYPE_OBJECT_INDEX) {
+ return objectSetter;
}
+ return MH.asType(MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE), pmt.changeParameterType(1, type));
default:
- assert false;
- return null;
+ throw new UnsupportedOperationException(forType + "=>" + type);
}
}
- private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class);
-
@SuppressWarnings("unused")
private static boolean isType(final Class<?> boxedForType, final Object x) {
- return x.getClass() == boxedForType;
+ return x != null && x.getClass() == boxedForType;
}
private static Class<? extends Number> getBoxedType(final Class<?> forType) {
@@ -634,7 +799,6 @@ public final class ObjectClassGenerator {
public static MethodHandle createGuardBoxedPrimitiveSetter(final Class<?> forType, final MethodHandle primitiveSetter, final MethodHandle objectSetter) {
final Class<? extends Number> boxedForType = getBoxedType(forType);
//object setter that checks for primitive if current type is primitive
-
return MH.guardWithTest(
MH.insertArguments(
MH.dropArguments(
@@ -648,62 +812,6 @@ public final class ObjectClassGenerator {
objectSetter.type()),
objectSetter);
}
-
- /**
- * This is similar to the {@link ObjectClassGenerator#createGetter} function. Performs
- * the necessary operations to massage a setter operand of type {@code type} to
- * fit into the primitive field (if primitive and dual fields is enabled) or into
- * the object field (box if primitive and dual fields is disabled)
- *
- * @param forType representation of the underlying object
- * @param type representation of field to write, and setter signature
- * @param primitiveSetter setter that writes to the primitive field (null if Objects Only)
- * @param objectSetter setter that writes to the object field
- *
- * @return the setter for the given representation that takes a {@code type}
- */
- public static MethodHandle createSetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveSetter, final MethodHandle objectSetter) {
- assert forType != null;
-
- final int fti = getAccessorTypeIndex(forType);
- final int ti = getAccessorTypeIndex(type);
-
- if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) {
- if (ti == TYPE_OBJECT_INDEX) {
- return objectSetter;
- }
-
- return MH.asType(objectSetter, objectSetter.type().changeParameterType(1, type));
- }
-
- assert !OBJECT_FIELDS_ONLY;
-
- final MethodType pmt = primitiveSetter.type();
-
- switch (fti) {
- case TYPE_INT_INDEX:
- case TYPE_LONG_INDEX:
- switch (ti) {
- case TYPE_INT_INDEX:
- return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class));
- case TYPE_LONG_INDEX:
- return primitiveSetter;
- case TYPE_DOUBLE_INDEX:
- return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE);
- default:
- return objectSetter;
- }
- case TYPE_DOUBLE_INDEX:
- if (ti == TYPE_OBJECT_INDEX) {
- return objectSetter;
- }
- return MH.asType(MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE), pmt.changeParameterType(1, type));
- default:
- assert false;
- return null;
- }
- }
-
/**
* Add padding to field count to avoid creating too many classes and have some spare fields
* @param count the field count
@@ -713,80 +821,49 @@ public final class ObjectClassGenerator {
return count / FIELD_PADDING * FIELD_PADDING + FIELD_PADDING;
}
- //
- // Provide generic getters and setters for undefined types. If a type is undefined, all
- // and marshals the set to the correct setter depending on the type of the value being set.
- // Note that there are no actual undefined versions of int, long and double in JavaScript,
- // but executing toInt32, toLong and toNumber always returns a working result, 0, 0L or NaN
- //
-
- /** The value of Undefined cast to an int32 */
- public static final int UNDEFINED_INT = 0;
- /** The value of Undefined cast to a long */
- public static final long UNDEFINED_LONG = 0L;
- /** The value of Undefined cast to a double */
- public static final double UNDEFINED_DOUBLE = Double.NaN;
-
- /**
- * Compute type name for correct undefined getter
- * @param type the type
- * @return name of getter
- */
- private static String typeName(final Type type) {
- String name = type.getTypeClass().getName();
- final int dot = name.lastIndexOf('.');
- if (dot != -1) {
- name = name.substring(dot + 1);
- }
- return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types));
}
/**
- * Handles for undefined getters of the different types
- */
- private static final MethodHandle[] GET_UNDEFINED = new MethodHandle[ObjectClassGenerator.getNumberOfAccessorTypes()];
-
- /**
- * Used to wrap getters for undefined values, where this matters. Currently only in dual fields.
- * If an object starts out as undefined it needs special getters until it has been assigned
- * something the first time
+ * Describes the allocator class name and property map for a constructor function with the specified
+ * number of "this" properties that it initializes.
*
- * @param returnType type to cast the undefined to
- *
- * @return undefined as returnType
*/
- public static MethodHandle getUndefined(final Class<?> returnType) {
- return GET_UNDEFINED[ObjectClassGenerator.getAccessorTypeIndex(returnType)];
- }
+ public static class AllocatorDescriptor {
+ private final String allocatorClassName;
+ private final PropertyMap allocatorMap;
- static {
- int pos = 0;
- for (final Type type : ACCESSOR_TYPES) {
- GET_UNDEFINED[pos++] = findOwnMH("getUndefined" + typeName(type), type.getTypeClass(), Object.class);
+ /**
+ * Creates a new allocator descriptor
+ * @param thisProperties the number of "this" properties that the function initializes
+ */
+ public AllocatorDescriptor(final int thisProperties) {
+ final int paddedFieldCount = getPaddedFieldCount(thisProperties);
+ this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount));
+ this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0);
}
- }
-
- @SuppressWarnings("unused")
- private static int getUndefinedInt(final Object obj) {
- return UNDEFINED_INT;
- }
- @SuppressWarnings("unused")
- private static long getUndefinedLong(final Object obj) {
- return UNDEFINED_LONG;
- }
-
- @SuppressWarnings("unused")
- private static double getUndefinedDouble(final Object obj) {
- return UNDEFINED_DOUBLE;
- }
+ /**
+ * Returns the name of the class that the function allocates
+ * @return the name of the class that the function allocates
+ */
+ public String getAllocatorClassName() {
+ return allocatorClassName;
+ }
- @SuppressWarnings("unused")
- private static Object getUndefinedObject(final Object obj) {
- return ScriptRuntime.UNDEFINED;
- }
+ /**
+ * Returns the allocator map for the function.
+ * @return the allocator map for the function.
+ */
+ public PropertyMap getAllocatorMap() {
+ return allocatorMap;
+ }
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types));
+ @Override
+ public String toString() {
+ return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+ allocatorMap.size() + "]";
+ }
}
}
diff --git a/src/jdk/nashorn/internal/codegen/ObjectCreator.java b/src/jdk/nashorn/internal/codegen/ObjectCreator.java
index d129d591..1a09ca62 100644
--- a/src/jdk/nashorn/internal/codegen/ObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java
@@ -28,22 +28,21 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
import java.util.List;
-import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* Base class for object creation code generation.
+ * @param <T> value type
*/
-public abstract class ObjectCreator {
+public abstract class ObjectCreator<T> {
- /** List of keys to initiate in this ObjectCreator */
- protected final List<String> keys;
-
- /** List of symbols to initiate in this ObjectCreator */
- protected final List<Symbol> symbols;
+ /** List of keys & symbols to initiate in this ObjectCreator */
+ final List<MapTuple<T>> tuples;
/** Code generator */
- protected final CodeGenerator codegen;
+ final CodeGenerator codegen;
/** Property map */
protected PropertyMap propertyMap;
@@ -55,15 +54,13 @@ public abstract class ObjectCreator {
* Constructor
*
* @param codegen the code generator
- * @param keys the keys
- * @param symbols the symbols corresponding to keys, same index
+ * @param tuples key,symbol,value (optional) tuples
* @param isScope is this object scope
* @param hasArguments does the created object have an "arguments" property
*/
- protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean hasArguments) {
+ ObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) {
this.codegen = codegen;
- this.keys = keys;
- this.symbols = symbols;
+ this.tuples = tuples;
this.isScope = isScope;
this.hasArguments = hasArguments;
}
@@ -85,8 +82,8 @@ public abstract class ObjectCreator {
* @param clazz type of MapCreator
* @return map creator instantiated by type
*/
- protected MapCreator newMapCreator(final Class<?> clazz) {
- return new MapCreator(clazz, keys, symbols);
+ protected MapCreator<?> newMapCreator(final Class<? extends ScriptObject> clazz) {
+ return new MapCreator<>(clazz, tuples);
}
/**
@@ -107,6 +104,10 @@ public abstract class ObjectCreator {
return method;
}
+ PropertyMap getMap() {
+ return propertyMap;
+ }
+
/**
* Is this a scope object
* @return true if scope
@@ -122,4 +123,27 @@ public abstract class ObjectCreator {
protected boolean hasArguments() {
return hasArguments;
}
+
+ /**
+ * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
+ *
+ * @param value Value to load.
+ * @param type the type of the value to load
+ */
+ protected abstract void loadValue(T value, Type type);
+
+ MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) {
+ loadValue(tuple.value, tuple.type);
+ if (pack && tuple.isPrimitive()) {
+ method.pack();
+ } else {
+ method.convert(Type.OBJECT);
+ }
+ return method;
+ }
+
+ MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
+ return loadTuple(method, tuple, true);
+ }
+
}
diff --git a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
new file mode 100644
index 00000000..c8029070
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.ir.PropertyNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WhileNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.ScriptObject;
+
+/**
+ * Assigns optimistic types to expressions that can have them. This class mainly contains logic for which expressions
+ * must not ever be marked as optimistic, assigning narrowest non-invalidated types to program points from the
+ * compilation environment, as well as initializing optimistic types of global properties for scripts.
+ */
+final class OptimisticTypesCalculator extends NodeVisitor<LexicalContext> {
+
+ final Compiler compiler;
+
+ // Per-function bit set of program points that must never be optimistic.
+ final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
+
+ OptimisticTypesCalculator(final Compiler compiler) {
+ super(new LexicalContext());
+ this.compiler = compiler;
+ }
+
+ @Override
+ public boolean enterAccessNode(final AccessNode accessNode) {
+ tagNeverOptimistic(accessNode.getBase());
+ return true;
+ }
+
+ @Override
+ public boolean enterPropertyNode(final PropertyNode propertyNode) {
+ if(propertyNode.getKeyName().equals(ScriptObject.PROTO_PROPERTY_NAME)) {
+ tagNeverOptimistic(propertyNode.getValue());
+ }
+ return super.enterPropertyNode(propertyNode);
+ }
+
+ @Override
+ public boolean enterBinaryNode(final BinaryNode binaryNode) {
+ if(binaryNode.isAssignment()) {
+ final Expression lhs = binaryNode.lhs();
+ if(!binaryNode.isSelfModifying()) {
+ tagNeverOptimistic(lhs);
+ }
+ if(lhs instanceof IdentNode) {
+ final Symbol symbol = ((IdentNode)lhs).getSymbol();
+ // Assignment to internal symbols is never optimistic, except for self-assignment expressions
+ if(symbol.isInternal() && !binaryNode.rhs().isSelfModifying()) {
+ tagNeverOptimistic(binaryNode.rhs());
+ }
+ }
+ } else if(binaryNode.isTokenType(TokenType.INSTANCEOF)) {
+ tagNeverOptimistic(binaryNode.lhs());
+ tagNeverOptimistic(binaryNode.rhs());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean enterCallNode(final CallNode callNode) {
+ tagNeverOptimistic(callNode.getFunction());
+ return true;
+ }
+
+ @Override
+ public boolean enterCatchNode(final CatchNode catchNode) {
+ // Condition is never optimistic (always coerced to boolean).
+ tagNeverOptimistic(catchNode.getExceptionCondition());
+ return true;
+ }
+
+ @Override
+ public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+ final Expression expr = expressionStatement.getExpression();
+ if(!expr.isSelfModifying()) {
+ tagNeverOptimistic(expr);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean enterForNode(final ForNode forNode) {
+ if(forNode.isForIn()) {
+ // for..in has the iterable in its "modify"
+ tagNeverOptimistic(forNode.getModify());
+ } else {
+ // Test is never optimistic (always coerced to boolean).
+ tagNeverOptimisticLoopTest(forNode);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ if (!neverOptimistic.isEmpty() && compiler.isOnDemandCompilation()) {
+ // This is a nested function, and we're doing on-demand compilation. In these compilations, we never descend
+ // into nested functions.
+ return false;
+ }
+ neverOptimistic.push(new BitSet());
+ return true;
+ }
+
+ @Override
+ public boolean enterIfNode(final IfNode ifNode) {
+ // Test is never optimistic (always coerced to boolean).
+ tagNeverOptimistic(ifNode.getTest());
+ return true;
+ }
+
+ @Override
+ public boolean enterIndexNode(final IndexNode indexNode) {
+ tagNeverOptimistic(indexNode.getBase());
+ return true;
+ }
+
+ @Override
+ public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+ // Test is never optimistic (always coerced to boolean).
+ tagNeverOptimistic(ternaryNode.getTest());
+ return true;
+ }
+
+ @Override
+ public boolean enterUnaryNode(final UnaryNode unaryNode) {
+ if(unaryNode.isTokenType(TokenType.NOT) || unaryNode.isTokenType(TokenType.NEW)) {
+ // Operand of boolean negation is never optimistic (always coerced to boolean).
+ // Operand of "new" is never optimistic (always coerced to Object).
+ tagNeverOptimistic(unaryNode.getExpression());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean enterVarNode(final VarNode varNode) {
+ tagNeverOptimistic(varNode.getName());
+ return true;
+ }
+
+ @Override
+ public boolean enterWhileNode(final WhileNode whileNode) {
+ // Test is never optimistic (always coerced to boolean).
+ tagNeverOptimisticLoopTest(whileNode);
+ return true;
+ }
+
+ @Override
+ protected Node leaveDefault(final Node node) {
+ if(node instanceof Optimistic) {
+ return leaveOptimistic((Optimistic)node);
+ }
+ return node;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ neverOptimistic.pop();
+ return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED);
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ final Symbol symbol = identNode.getSymbol();
+ if(symbol == null) {
+ assert identNode.isPropertyName();
+ return identNode;
+ } else if(symbol.isBytecodeLocal()) {
+ // Identifiers accessing bytecode local variables will never be optimistic, as type calculation phase over
+ // them will always assign them statically provable types. Note that access to function parameters can still
+ // be optimistic if the parameter needs to be in scope as it's used by a nested function.
+ return identNode;
+ } else if(symbol.isParam() && lc.getCurrentFunction().isVarArg()) {
+ // Parameters in vararg methods are not optimistic; we always access them using Object getters.
+ return identNode.setType(identNode.getMostPessimisticType());
+ } else {
+ assert symbol.isScope();
+ return leaveOptimistic(identNode);
+ }
+ }
+
+ private Expression leaveOptimistic(final Optimistic opt) {
+ final int pp = opt.getProgramPoint();
+ if(isValid(pp) && !neverOptimistic.peek().get(pp)) {
+ return (Expression)opt.setType(compiler.getOptimisticType(opt));
+ }
+ return (Expression)opt;
+ }
+
+ private void tagNeverOptimistic(final Expression expr) {
+ if(expr instanceof Optimistic) {
+ final int pp = ((Optimistic)expr).getProgramPoint();
+ if(isValid(pp)) {
+ neverOptimistic.peek().set(pp);
+ }
+ }
+ }
+
+ private void tagNeverOptimisticLoopTest(final LoopNode loopNode) {
+ final JoinPredecessorExpression test = loopNode.getTest();
+ if(test != null) {
+ tagNeverOptimistic(test.getExpression());
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
new file mode 100644
index 00000000..53a107e6
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.codegen;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.AccessController;
+import java.security.MessageDigest;
+import java.security.PrivilegedAction;
+import java.text.SimpleDateFormat;
+import java.util.Base64;
+import java.util.Date;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * Static utility that encapsulates persistence of type information for functions compiled with optimistic
+ * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized,
+ * the type information for deoptimization is stored in a cache file. If the same function is compiled in a
+ * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system
+ * to skip a lot of intermediate recompilations and immediately emit a version of the code that has its
+ * optimistic types at (or near) the steady state.
+ * </p><p>
+ * Normally, the type info persistence feature is disabled. When the {@code nashorn.typeInfo.maxFiles} system
+ * property is specified with a value greater than 0, it is enabled and operates in an operating-system
+ * specific per-user cache directory. You can override the directory by specifying it in the
+ * {@code nashorn.typeInfo.cacheDir} directory. The maximum number of files is softly enforced by a task that
+ * cleans up the directory periodically on a separate thread. It is run after some delay after a new file is
+ * added to the cache. The default delay is 20 seconds, and can be set using the
+ * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word
+ * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is
+ * allowed to grow without limits.
+ */
+public final class OptimisticTypesPersistence {
+ // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is
+ // dependent on the application; setting it to e.g. 20000 is probably good enough for most uses and will
+ // usually cap the cache directory to about 80MB presuming a 4kB filesystem allocation unit. There is one
+ // file per JavaScript function.
+ private static final int DEFAULT_MAX_FILES = 0;
+ // Constants for signifying that the cache should not be limited
+ private static final int UNLIMITED_FILES = -1;
+ // Maximum number of files that should be cached on disk. The maximum will be softly enforced.
+ private static final int MAX_FILES = getMaxFiles();
+ // Number of seconds to wait between adding a new file to the cache and running a cleanup process
+ private static final int DEFAULT_CLEANUP_DELAY = 20;
+ private static final int CLEANUP_DELAY = Math.max(0, Options.getIntProperty(
+ "nashorn.typeInfo.cleanupDelaySeconds", DEFAULT_CLEANUP_DELAY));
+ // The name of the default subdirectory within the system cache directory where we store type info.
+ private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo";
+ // The directory where we cache type info
+ private static final File baseCacheDir = createBaseCacheDir();
+ private static final File cacheDir = createCacheDir(baseCacheDir);
+ // In-process locks to make sure we don't have a cross-thread race condition manipulating any file.
+ private static final Object[] locks = cacheDir == null ? null : createLockArray();
+ // Only report one read/write error every minute
+ private static final long ERROR_REPORT_THRESHOLD = 60000L;
+
+ private static volatile long lastReportedError;
+ private static final AtomicBoolean scheduledCleanup;
+ private static final Timer cleanupTimer;
+ static {
+ if (baseCacheDir == null || MAX_FILES == UNLIMITED_FILES) {
+ scheduledCleanup = null;
+ cleanupTimer = null;
+ } else {
+ scheduledCleanup = new AtomicBoolean();
+ cleanupTimer = new Timer(true);
+ }
+ }
+ /**
+ * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed
+ * to {@link #load(Object)} and {@link #store(Object, Map)} methods.
+ * @param source the source where the function comes from
+ * @param functionId the unique ID number of the function within the source
+ * @param paramTypes the types of the function parameters (as persistence is per parameter type
+ * specialization).
+ * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
+ */
+ public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
+ if(cacheDir == null) {
+ return null;
+ }
+ final StringBuilder b = new StringBuilder(48);
+ // Base64-encode the digest of the source, and append the function id.
+ b.append(source.getDigest()).append('-').append(functionId);
+ // Finally, if this is a parameter-type specialized version of the function, add the parameter types
+ // to the file name.
+ if(paramTypes != null && paramTypes.length > 0) {
+ b.append('-');
+ for(final Type t: paramTypes) {
+ b.append(Type.getShortSignatureDescriptor(t));
+ }
+ }
+ return new LocationDescriptor(new File(cacheDir, b.toString()));
+ }
+
+ private static final class LocationDescriptor {
+ private final File file;
+
+ LocationDescriptor(final File file) {
+ this.file = file;
+ }
+ }
+
+
+ /**
+ * Stores the map of optimistic types for a given function.
+ * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
+ * {@link #getLocationDescriptor(Source, int, Type[])}.
+ * @param optimisticTypes the map of optimistic types.
+ */
+ @SuppressWarnings("resource")
+ public static void store(final Object locationDescriptor, final Map<Integer, Type> optimisticTypes) {
+ if(locationDescriptor == null || optimisticTypes.isEmpty()) {
+ return;
+ }
+ final File file = ((LocationDescriptor)locationDescriptor).file;
+
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ synchronized(getFileLock(file)) {
+ if (!file.exists()) {
+ // If the file already exists, we aren't increasing the number of cached files, so
+ // don't schedule cleanup.
+ scheduleCleanup();
+ }
+ try (final FileOutputStream out = new FileOutputStream(file)) {
+ out.getChannel().lock(); // lock exclusive
+ final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out));
+ Type.writeTypeMap(optimisticTypes, dout);
+ dout.flush();
+ } catch(final Exception e) {
+ reportError("write", file, e);
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Loads the map of optimistic types for a given function.
+ * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
+ * {@link #getLocationDescriptor(Source, int, Type[])}.
+ * @return the map of optimistic types, or null if persisted type information could not be retrieved.
+ */
+ @SuppressWarnings("resource")
+ public static Map<Integer, Type> load(final Object locationDescriptor) {
+ if (locationDescriptor == null) {
+ return null;
+ }
+ final File file = ((LocationDescriptor)locationDescriptor).file;
+ return AccessController.doPrivileged(new PrivilegedAction<Map<Integer, Type>>() {
+ @Override
+ public Map<Integer, Type> run() {
+ try {
+ if(!file.isFile()) {
+ return null;
+ }
+ synchronized(getFileLock(file)) {
+ try (final FileInputStream in = new FileInputStream(file)) {
+ in.getChannel().lock(0, Long.MAX_VALUE, true); // lock shared
+ final DataInputStream din = new DataInputStream(new BufferedInputStream(in));
+ return Type.readTypeMap(din);
+ }
+ }
+ } catch (final Exception e) {
+ reportError("read", file, e);
+ return null;
+ }
+ }
+ });
+ }
+
+ private static void reportError(final String msg, final File file, final Exception e) {
+ final long now = System.currentTimeMillis();
+ if(now - lastReportedError > ERROR_REPORT_THRESHOLD) {
+ reportError(String.format("Failed to %s %s", msg, file), e);
+ lastReportedError = now;
+ }
+ }
+
+ /**
+ * Logs an error message with warning severity (reasoning being that we're reporting an error that'll disable the
+ * type info cache, but it's only logged as a warning because that doesn't prevent Nashorn from running, it just
+ * disables a performance-enhancing cache).
+ * @param msg the message to log
+ * @param e the exception that represents the error.
+ */
+ private static void reportError(final String msg, final Exception e) {
+ getLogger().warning(msg, "\n", exceptionToString(e));
+ }
+
+ /**
+ * A helper that prints an exception stack trace into a string. We have to do this as if we just pass the exception
+ * to {@link DebugLogger#warning(Object...)}, it will only log the exception message and not the stack, making
+ * problems harder to diagnose.
+ * @param e the exception
+ * @return the string representation of {@link Exception#printStackTrace()} output.
+ */
+ private static String exceptionToString(final Exception e) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw, false);
+ e.printStackTrace(pw);
+ pw.flush();
+ return sw.toString();
+ }
+
+ private static File createBaseCacheDir() {
+ if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
+ return null;
+ }
+ try {
+ return createBaseCacheDirPrivileged();
+ } catch(final Exception e) {
+ reportError("Failed to create cache dir", e);
+ return null;
+ }
+ }
+
+ private static File createBaseCacheDirPrivileged() {
+ return AccessController.doPrivileged(new PrivilegedAction<File>() {
+ @Override
+ public File run() {
+ final String explicitDir = System.getProperty("nashorn.typeInfo.cacheDir");
+ final File dir;
+ if(explicitDir != null) {
+ dir = new File(explicitDir);
+ } else {
+ // When no directory is explicitly specified, get an operating system specific cache
+ // directory, and create "com.oracle.java.NashornTypeInfo" in it.
+ final File systemCacheDir = getSystemCacheDir();
+ dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME);
+ if (isSymbolicLink(dir)) {
+ return null;
+ }
+ }
+ return dir;
+ }
+ });
+ }
+
+ private static File createCacheDir(final File baseDir) {
+ if (baseDir == null) {
+ return null;
+ }
+ try {
+ return createCacheDirPrivileged(baseDir);
+ } catch(final Exception e) {
+ reportError("Failed to create cache dir", e);
+ return null;
+ }
+ }
+
+ private static File createCacheDirPrivileged(final File baseDir) {
+ return AccessController.doPrivileged(new PrivilegedAction<File>() {
+ @Override
+ public File run() {
+ final String versionDirName;
+ try {
+ versionDirName = getVersionDirName();
+ } catch(final Exception e) {
+ reportError("Failed to calculate version dir name", e);
+ return null;
+ }
+ final File versionDir = new File(baseDir, versionDirName);
+ if (isSymbolicLink(versionDir)) {
+ return null;
+ }
+ versionDir.mkdirs();
+ if (versionDir.isDirectory()) {
+ getLogger().info("Optimistic type persistence directory is " + versionDir);
+ return versionDir;
+ }
+ getLogger().warning("Could not create optimistic type persistence directory " + versionDir);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Returns an operating system specific root directory for cache files.
+ * @return an operating system specific root directory for cache files.
+ */
+ private static File getSystemCacheDir() {
+ final String os = System.getProperty("os.name", "generic");
+ if("Mac OS X".equals(os)) {
+ // Mac OS X stores caches in ~/Library/Caches
+ return new File(new File(System.getProperty("user.home"), "Library"), "Caches");
+ } else if(os.startsWith("Windows")) {
+ // On Windows, temp directory is the best approximation of a cache directory, as its contents
+ // persist across reboots and various cleanup utilities know about it. java.io.tmpdir normally
+ // points to a user-specific temp directory, %HOME%\LocalSettings\Temp.
+ return new File(System.getProperty("java.io.tmpdir"));
+ } else {
+ // In other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache"
+ return new File(System.getProperty("user.home"), ".cache");
+ }
+ }
+
+ /**
+ * In order to ensure that changes in Nashorn code don't cause corruption in the data, we'll create a
+ * per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath
+ * for nashorn is local directory (e.g. during development), this will create the string "dev-" followed by the
+ * timestamp of the most recent .class file.
+ *
+ * @return digest of currently running nashorn
+ * @throws Exception if digest could not be created
+ */
+ public static String getVersionDirName() throws Exception {
+ // NOTE: getResource("") won't work if the JAR file doesn't have directory entries (and JAR files in JDK distro
+ // don't, or at least it's a bad idea counting on it). Alternatively, we could've tried
+ // getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness
+ // to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our
+ // package is to have a small non-class anchor file and start out from its URL.
+ final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties");
+ final String protocol = url.getProtocol();
+ if (protocol.equals("jar")) {
+ // Normal deployment: nashorn.jar
+ final String jarUrlFile = url.getFile();
+ final String filePath = jarUrlFile.substring(0, jarUrlFile.indexOf('!'));
+ final URL file = new URL(filePath);
+ try (final InputStream in = file.openStream()) {
+ final byte[] buf = new byte[128*1024];
+ final MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ for(;;) {
+ final int l = in.read(buf);
+ if(l == -1) {
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(digest.digest());
+ }
+ digest.update(buf, 0, l);
+ }
+ }
+ } else if(protocol.equals("file")) {
+ // Development
+ final String fileStr = url.getFile();
+ final String className = OptimisticTypesPersistence.class.getName();
+ final int packageNameLen = className.lastIndexOf('.');
+ final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1);
+ final File dir = new File(dirStr);
+ return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(
+ dir, 0L)));
+ } else {
+ throw new AssertionError();
+ }
+ }
+
+ private static long getLastModifiedClassFile(final File dir, final long max) {
+ long currentMax = max;
+ for(final File f: dir.listFiles()) {
+ if(f.getName().endsWith(".class")) {
+ final long lastModified = f.lastModified();
+ if (lastModified > currentMax) {
+ currentMax = lastModified;
+ }
+ } else if (f.isDirectory()) {
+ final long lastModified = getLastModifiedClassFile(f, currentMax);
+ if (lastModified > currentMax) {
+ currentMax = lastModified;
+ }
+ }
+ }
+ return currentMax;
+ }
+
+ /**
+ * Returns true if the specified file is a symbolic link, and also logs a warning if it is.
+ * @param file the file
+ * @return true if file is a symbolic link, false otherwise.
+ */
+ private static boolean isSymbolicLink(final File file) {
+ if (Files.isSymbolicLink(file.toPath())) {
+ getLogger().warning("Directory " + file + " is a symlink");
+ return true;
+ }
+ return false;
+ }
+
+ private static Object[] createLockArray() {
+ final Object[] lockArray = new Object[Runtime.getRuntime().availableProcessors() * 2];
+ for (int i = 0; i < lockArray.length; ++i) {
+ lockArray[i] = new Object();
+ }
+ return lockArray;
+ }
+
+ private static Object getFileLock(final File file) {
+ return locks[(file.hashCode() & Integer.MAX_VALUE) % locks.length];
+ }
+
+ private static DebugLogger getLogger() {
+ try {
+ return Context.getContext().getLogger(RecompilableScriptFunctionData.class);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ return DebugLogger.DISABLED_LOGGER;
+ }
+ }
+
+ private static void scheduleCleanup() {
+ if (MAX_FILES != UNLIMITED_FILES && scheduledCleanup.compareAndSet(false, true)) {
+ cleanupTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ scheduledCleanup.set(false);
+ try {
+ doCleanup();
+ } catch (final IOException e) {
+ // Ignore it. While this is unfortunate, we don't have good facility for reporting
+ // this, as we're running in a thread that has no access to Context, so we can't grab
+ // a DebugLogger.
+ }
+ }
+ }, TimeUnit.SECONDS.toMillis(CLEANUP_DELAY));
+ }
+ }
+
+ private static void doCleanup() throws IOException {
+ final Path[] files = getAllRegularFilesInLastModifiedOrder();
+ final int nFiles = files.length;
+ final int filesToDelete = Math.max(0, nFiles - MAX_FILES);
+ int filesDeleted = 0;
+ for (int i = 0; i < nFiles && filesDeleted < filesToDelete; ++i) {
+ try {
+ Files.deleteIfExists(files[i]);
+ // Even if it didn't exist, we increment filesDeleted; it existed a moment earlier; something
+ // else deleted it for us; that's okay with us.
+ filesDeleted++;
+ } catch (final Exception e) {
+ // does not increase filesDeleted
+ }
+ files[i] = null; // gc eligible
+ }
+ }
+
+ private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException {
+ try (final Stream<Path> filesStream = Files.walk(baseCacheDir.toPath())) {
+ // TODO: rewrite below once we can use JDK8 syntactic constructs
+ return filesStream
+ .filter(new Predicate<Path>() {
+ @Override
+ public boolean test(final Path path) {
+ return !Files.isDirectory(path);
+ }
+ })
+ .map(new Function<Path, PathAndTime>() {
+ @Override
+ public PathAndTime apply(final Path path) {
+ return new PathAndTime(path);
+ }
+ })
+ .sorted()
+ .map(new Function<PathAndTime, Path>() {
+ @Override
+ public Path apply(final PathAndTime pathAndTime) {
+ return pathAndTime.path;
+ }
+ })
+ .toArray(new IntFunction<Path[]>() { // Replace with Path::new
+ @Override
+ public Path[] apply(final int length) {
+ return new Path[length];
+ }
+ });
+ }
+ }
+
+ private static class PathAndTime implements Comparable<PathAndTime> {
+ private final Path path;
+ private final long time;
+
+ PathAndTime(final Path path) {
+ this.path = path;
+ this.time = getTime(path);
+ }
+
+ @Override
+ public int compareTo(final PathAndTime other) {
+ return Long.compare(time, other.time);
+ }
+
+ private static long getTime(final Path path) {
+ try {
+ return Files.getLastModifiedTime(path).toMillis();
+ } catch (final IOException e) {
+ // All files for which we can't retrieve the last modified date will be considered oldest.
+ return -1L;
+ }
+ }
+ }
+
+ private static int getMaxFiles() {
+ final String str = Options.getStringProperty("nashorn.typeInfo.maxFiles", null);
+ if (str == null) {
+ return DEFAULT_MAX_FILES;
+ } else if ("unlimited".equals(str)) {
+ return UNLIMITED_FILES;
+ }
+ return Math.max(0, Integer.parseInt(str));
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/ProgramPoints.java b/src/jdk/nashorn/internal/codegen/ProgramPoints.java
new file mode 100644
index 00000000..4606989e
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/ProgramPoints.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.FIRST_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.MAX_PROGRAM_POINT_VALUE;
+
+import java.util.HashSet;
+import java.util.Set;
+import jdk.nashorn.internal.IntDeque;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Find program points in the code that are needed for optimistic assumptions
+ */
+class ProgramPoints extends NodeVisitor<LexicalContext> {
+
+ private final IntDeque nextProgramPoint = new IntDeque();
+ private final Set<Node> noProgramPoint = new HashSet<>();
+
+ ProgramPoints() {
+ super(new LexicalContext());
+ }
+
+ private int next() {
+ final int next = nextProgramPoint.getAndIncrement();
+ if(next > MAX_PROGRAM_POINT_VALUE) {
+ throw new AssertionError("Function has more than " + MAX_PROGRAM_POINT_VALUE + " program points");
+ }
+ return next;
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ nextProgramPoint.push(FIRST_PROGRAM_POINT);
+ return true;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ nextProgramPoint.pop();
+ return functionNode;
+ }
+
+ private Expression setProgramPoint(final Optimistic optimistic) {
+ if (noProgramPoint.contains(optimistic)) {
+ return (Expression)optimistic;
+ }
+ return (Expression)(optimistic.canBeOptimistic() ? optimistic.setProgramPoint(next()) : optimistic);
+ }
+
+ @Override
+ public boolean enterVarNode(final VarNode varNode) {
+ noProgramPoint.add(varNode.getName());
+ return true;
+ }
+
+ @Override
+ public boolean enterIdentNode(final IdentNode identNode) {
+ if (identNode.isInternal()) {
+ noProgramPoint.add(identNode);
+ }
+ return true;
+ }
+
+ @Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ if(identNode.isPropertyName()) {
+ return identNode;
+ }
+ return setProgramPoint(identNode);
+ }
+
+ @Override
+ public Node leaveCallNode(final CallNode callNode) {
+ return setProgramPoint(callNode);
+ }
+
+ @Override
+ public Node leaveAccessNode(final AccessNode accessNode) {
+ return setProgramPoint(accessNode);
+ }
+
+ @Override
+ public Node leaveIndexNode(final IndexNode indexNode) {
+ return setProgramPoint(indexNode);
+ }
+
+ @Override
+ public Node leaveBinaryNode(final BinaryNode binaryNode) {
+ return setProgramPoint(binaryNode);
+ }
+
+ @Override
+ public Node leaveUnaryNode(final UnaryNode unaryNode) {
+ return setProgramPoint(unaryNode);
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java b/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
deleted file mode 100644
index 4056ec0c..00000000
--- a/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Range;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.Assignment;
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LoopNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.DebugLogger;
-
-/**
- * Range analysis and narrowing of type where it can be proven
- * that there is no spillover, e.g.
- *
- * function func(c) {
- * var v = c & 0xfff;
- * var w = c & 0xeee;
- * var x = v * w;
- * return x;
- * }
- *
- * Proves that the multiplication never exceeds 24 bits and can thus be an int
- */
-final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
- static final DebugLogger LOG = new DebugLogger("ranges");
-
- private static final Range.Functionality RANGE = new Range.Functionality(LOG);
-
- private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
-
- RangeAnalyzer() {
- super(new LexicalContext());
- }
-
- @Override
- public boolean enterForNode(final ForNode forNode) {
- //conservatively attempt to identify the loop counter. Null means that it wasn't
- //properly identified and that no optimizations can be made with it - its range is
- //simply unknown in that case, if it is assigned in the loop
- final Symbol counter = findLoopCounter(forNode);
- LOG.fine("Entering forNode " + forNode + " counter = " + counter);
- if (counter != null && !assignedInLoop(forNode, counter)) {
- loopCounters.put(forNode, counter);
- }
- return true;
- }
-
- //destination visited
- private Symbol setRange(final Expression dest, final Range range) {
- if (range.isUnknown()) {
- return null;
- }
-
- final Symbol symbol = dest.getSymbol();
- assert symbol != null : dest + " " + dest.getClass() + " has no symbol";
- assert symbol.getRange() != null : symbol + " has no range";
- final Range symRange = RANGE.join(symbol.getRange(), range);
-
- //anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
- if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) {
- symbol.setRange(Range.createGenericRange());
- return symbol;
- }
-
- if (!symRange.equals(symbol.getRange())) {
- LOG.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
- symbol.setRange(symRange);
- }
-
- return null;
- }
-
- @Override
- public Node leaveADD(final BinaryNode node) {
- setRange(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveSUB(final BinaryNode node) {
- setRange(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveMUL(final BinaryNode node) {
- setRange(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveDIV(final BinaryNode node) {
- setRange(node, RANGE.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveMOD(final BinaryNode node) {
- setRange(node, RANGE.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveBIT_AND(final BinaryNode node) {
- setRange(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveBIT_OR(final BinaryNode node) {
- setRange(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveBIT_XOR(final BinaryNode node) {
- setRange(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveSAR(final BinaryNode node) {
- setRange(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveSHL(final BinaryNode node) {
- setRange(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveSHR(final BinaryNode node) {
- setRange(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- return node;
- }
-
- private Node leaveCmp(final BinaryNode node) {
- setRange(node, Range.createTypeRange(Type.BOOLEAN));
- return node;
- }
-
- @Override
- public Node leaveEQ(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveEQ_STRICT(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveNE(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveNE_STRICT(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveLT(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveLE(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveGT(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveGE(final BinaryNode node) {
- return leaveCmp(node);
- }
-
- @Override
- public Node leaveASSIGN(final BinaryNode node) {
- Range range = node.rhs().getSymbol().getRange();
- if (range.isUnknown()) {
- range = Range.createGenericRange();
- }
-
- setRange(node.lhs(), range);
- setRange(node, range);
-
- return node;
- }
-
- private Node leaveSelfModifyingAssign(final BinaryNode node, final Range range) {
- setRange(node.lhs(), range);
- setRange(node, range);
- return node;
- }
-
- private Node leaveSelfModifyingAssign(final UnaryNode node, final Range range) {
- setRange(node.rhs(), range);
- setRange(node, range);
- return node;
- }
-
- @Override
- public Node leaveASSIGN_ADD(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_SUB(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_MUL(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_DIV(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
- }
-
- @Override
- public Node leaveASSIGN_MOD(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
- }
-
- @Override
- public Node leaveASSIGN_BIT_AND(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_BIT_OR(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_BIT_XOR(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_SAR(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_SHR(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveASSIGN_SHL(final BinaryNode node) {
- return leaveSelfModifyingAssign(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
- }
-
- @Override
- public Node leaveDECINC(final UnaryNode node) {
- switch (node.tokenType()) {
- case DECPREFIX:
- case DECPOSTFIX:
- return leaveSelfModifyingAssign(node, RANGE.sub(node.rhs().getSymbol().getRange(), Range.createRange(1)));
- case INCPREFIX:
- case INCPOSTFIX:
- return leaveSelfModifyingAssign(node, RANGE.add(node.rhs().getSymbol().getRange(), Range.createRange(1)));
- default:
- assert false;
- return node;
- }
- }
-
- @Override
- public Node leaveADD(final UnaryNode node) {
- Range range = node.rhs().getSymbol().getRange();
- if (!range.getType().isNumeric()) {
- range = Range.createTypeRange(Type.NUMBER);
- }
- setRange(node, range);
- return node;
- }
-
- @Override
- public Node leaveBIT_NOT(final UnaryNode node) {
- setRange(node, Range.createTypeRange(Type.INT));
- return node;
- }
-
- @Override
- public Node leaveNOT(final UnaryNode node) {
- setRange(node, Range.createTypeRange(Type.BOOLEAN));
- return node;
- }
-
- @Override
- public Node leaveSUB(final UnaryNode node) {
- setRange(node, RANGE.neg(node.rhs().getSymbol().getRange()));
- return node;
- }
-
- @Override
- public Node leaveVarNode(final VarNode node) {
- if (node.isAssignment()) {
- Range range = node.getInit().getSymbol().getRange();
- range = range.isUnknown() ? Range.createGenericRange() : range;
-
- setRange(node.getName(), range);
- }
-
- return node;
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public boolean enterLiteralNode(final LiteralNode node) {
- // ignore array literals
- return !(node instanceof ArrayLiteralNode);
- }
-
- @Override
- public Node leaveLiteralNode(@SuppressWarnings("rawtypes") final LiteralNode node) {
- if (node.getType().isInteger()) {
- setRange(node, Range.createRange(node.getInt32()));
- } else if (node.getType().isNumber()) {
- setRange(node, Range.createRange(node.getNumber()));
- } else if (node.getType().isLong()) {
- setRange(node, Range.createRange(node.getLong()));
- } else if (node.getType().isBoolean()) {
- setRange(node, Range.createTypeRange(Type.BOOLEAN));
- } else {
- setRange(node, Range.createGenericRange());
- }
- return node;
- }
-
- @Override
- public boolean enterRuntimeNode(final RuntimeNode node) {
- // a runtime node that cannot be specialized is no point entering
- return node.getRequest().canSpecialize();
- }
-
- /**
- * Check whether a symbol is unsafely assigned in a loop - i.e. repeteadly assigned and
- * not being identified as the loop counter. That means we don't really know anything
- * about its range.
- * @param loopNode loop node
- * @param symbol symbol
- * @return true if assigned in loop
- */
- // TODO - this currently checks for nodes only - needs to be augmented for while nodes
- // assignment analysis is also very conservative
- private static boolean assignedInLoop(final LoopNode loopNode, final Symbol symbol) {
- final HashSet<Node> skip = new HashSet<>();
- final HashSet<Node> assignmentsInLoop = new HashSet<>();
-
- loopNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- private boolean assigns(final Node node, final Symbol s) {
- return node.isAssignment() && ((Assignment<?>)node).getAssignmentDest().getSymbol() == s;
- }
-
- @Override
- public boolean enterForNode(final ForNode forNode) {
- if (forNode.getInit() != null) {
- skip.add(forNode.getInit());
- }
- if (forNode.getModify() != null) {
- skip.add(forNode.getModify());
- }
- return true;
- }
-
- @Override
- public Node leaveDefault(final Node node) {
- //if this is an assignment to symbol
- if (!skip.contains(node) && assigns(node, symbol)) {
- assignmentsInLoop.add(node);
- }
- return node;
- }
- });
-
- return !assignmentsInLoop.isEmpty();
- }
-
- /**
- * Check for a loop counter. This is currently quite conservative, in that it only handles
- * x <= counter and x < counter.
- *
- * @param node loop node to check
- * @return
- */
- private static Symbol findLoopCounter(final LoopNode node) {
- final Expression test = node.getTest();
-
- if (test != null && test.isComparison()) {
- final BinaryNode binaryNode = (BinaryNode)test;
- final Expression lhs = binaryNode.lhs();
- final Expression rhs = binaryNode.rhs();
-
- //detect ident cmp int_literal
- if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode<?>)rhs).getType().isInteger()) {
- final Symbol symbol = lhs.getSymbol();
- final int margin = ((LiteralNode<?>)rhs).getInt32();
- final TokenType op = test.tokenType();
-
- switch (op) {
- case LT:
- case LE:
- symbol.setRange(RANGE.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
- return symbol;
- case GT:
- case GE:
- //setRange(lhs, Range.createRange(op == TokenType.GT ? margin + 1 : margin));
- //return symbol;
- default:
- break;
- }
- }
- }
-
- return null;
- }
-
- private boolean isLoopCounter(final LoopNode loopNode, final Symbol symbol) {
- //this only works if loop nodes aren't replaced by other ones during this transform, but they are not
- return loopCounters.get(loopNode) == symbol;
- }
-}
diff --git a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
new file mode 100644
index 00000000..57f9e681
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.util.ArrayList;
+import java.util.List;
+import jdk.nashorn.internal.ir.CompileUnitHolder;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Base class for a node visitor that replaces {@link CompileUnit}s in {@link CompileUnitHolder}s.
+ */
+abstract class ReplaceCompileUnits extends NodeVisitor<LexicalContext> {
+ ReplaceCompileUnits() {
+ super(new LexicalContext());
+ }
+
+ /**
+ * Override to provide a replacement for an old compile unit.
+ * @param oldUnit the old compile unit to replace
+ * @return the compile unit's replacement.
+ */
+ abstract CompileUnit getReplacement(final CompileUnit oldUnit);
+
+ CompileUnit getExistingReplacement(final CompileUnitHolder node) {
+ final CompileUnit oldUnit = node.getCompileUnit();
+ assert oldUnit != null;
+
+ final CompileUnit newUnit = getReplacement(oldUnit);
+ assert newUnit != null;
+
+ return newUnit;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode node) {
+ return node.setCompileUnit(lc, getExistingReplacement(node)).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
+ }
+
+ @Override
+ public Node leaveLiteralNode(final LiteralNode<?> node) {
+ if (node instanceof ArrayLiteralNode) {
+ final ArrayLiteralNode aln = (ArrayLiteralNode)node;
+ if (aln.getUnits() == null) {
+ return node;
+ }
+ final List<ArrayUnit> newArrayUnits = new ArrayList<>();
+ for (final ArrayUnit au : aln.getUnits()) {
+ newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
+ }
+ return aln.setUnits(lc, newArrayUnits);
+ }
+ return node;
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java b/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
index c9f3836b..b4d2f2da 100644
--- a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
+++ b/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
@@ -42,7 +42,6 @@ import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.RuntimeNode.Request;
import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -59,7 +58,7 @@ import jdk.nashorn.internal.runtime.linker.Bootstrap;
public final class RuntimeCallSite extends MutableCallSite {
static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
- private static final MethodHandle NEXT = findOwnMH("next", MethodHandle.class, String.class);
+ private static final MethodHandle NEXT = findOwnMH_V("next", MethodHandle.class, String.class);
private final RuntimeNode.Request request;
@@ -89,7 +88,7 @@ public final class RuntimeCallSite extends MutableCallSite {
}
/**
- * The first type to try to use for this genrated runtime node
+ * The first type to try to use for this generated runtime node
*
* @return a type
*/
@@ -351,19 +350,19 @@ public final class RuntimeCallSite extends MutableCallSite {
/** Unbox cache */
private static final Map<Class<?>, MethodHandle> UNBOX;
- private static final MethodHandle CHECKCAST = findOwnMH("checkcast", boolean.class, Class.class, Object.class);
- private static final MethodHandle CHECKCAST2 = findOwnMH("checkcast", boolean.class, Class.class, Object.class, Object.class);
- private static final MethodHandle ADDCHECK = findOwnMH("ADDcheck", boolean.class, int.class, int.class);
+ private static final MethodHandle CHECKCAST = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class);
+ private static final MethodHandle CHECKCAST2 = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class, Object.class);
+ private static final MethodHandle ADDCHECK = findOwnMH_S("ADDcheck", boolean.class, int.class, int.class);
/**
* Build maps of correct boxing operations
*/
static {
UNBOX = new HashMap<>();
- UNBOX.put(Boolean.class, findOwnMH("unboxZ", int.class, Object.class));
- UNBOX.put(Integer.class, findOwnMH("unboxI", int.class, Object.class));
- UNBOX.put(Long.class, findOwnMH("unboxJ", long.class, Object.class));
- UNBOX.put(Number.class, findOwnMH("unboxD", double.class, Object.class));
+ UNBOX.put(Boolean.class, findOwnMH_S("unboxZ", int.class, Object.class));
+ UNBOX.put(Integer.class, findOwnMH_S("unboxI", int.class, Object.class));
+ UNBOX.put(Long.class, findOwnMH_S("unboxJ", long.class, Object.class));
+ UNBOX.put(Number.class, findOwnMH_S("unboxD", double.class, Object.class));
METHODS = new HashMap<>();
@@ -375,9 +374,9 @@ public final class RuntimeCallSite extends MutableCallSite {
final boolean isCmp = Request.isComparison(req);
- METHODS.put(req.name() + "int", findOwnMH(req.name(), (isCmp ? boolean.class : int.class), int.class, int.class));
- METHODS.put(req.name() + "long", findOwnMH(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class));
- METHODS.put(req.name() + "double", findOwnMH(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class));
+ METHODS.put(req.name() + "int", findOwnMH_S(req.name(), (isCmp ? boolean.class : int.class), int.class, int.class));
+ METHODS.put(req.name() + "long", findOwnMH_S(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class));
+ METHODS.put(req.name() + "double", findOwnMH_S(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class));
}
}
@@ -674,12 +673,11 @@ public final class RuntimeCallSite extends MutableCallSite {
return ((Number)obj).doubleValue();
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- try {
- return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
- }
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
}
+ private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
+ }
}
diff --git a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
index da29ac05..078324cc 100644
--- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
+++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.codegen;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+
import java.util.Arrays;
import java.util.EnumSet;
import jdk.nashorn.internal.codegen.types.Type;
@@ -81,6 +83,7 @@ class SharedScopeCall {
this.valueType = valueType;
this.returnType = returnType;
this.paramTypes = paramTypes;
+ assert (flags & CALLSITE_OPTIMISTIC) == 0;
this.flags = flags;
// If paramTypes is not null this is a call, otherwise it's just a get.
this.isCall = paramTypes != null;
@@ -150,7 +153,10 @@ class SharedScopeCall {
method._goto(parentLoopStart);
method.label(parentLoopDone);
- method.dynamicGet(valueType, symbol.getName(), flags, isCall);
+ assert !isCall || valueType.isObject(); // Callables are always objects
+ // If flags are optimistic, but we're doing a call, remove optimistic flags from the getter, as they obviously
+ // only apply to the call.
+ method.dynamicGet(valueType, symbol.getName(), isCall ? CodeGenerator.nonOptimisticFlags(flags) : flags, isCall, false);
// If this is a get we're done, otherwise call the value as function.
if (isCall) {
@@ -159,11 +165,10 @@ class SharedScopeCall {
method.loadUndefined(Type.OBJECT);
int slot = 2;
for (final Type type : paramTypes) {
- method.load(type, slot++);
- if (type == Type.NUMBER || type == Type.LONG) {
- slot++;
- }
+ method.load(type, slot);
+ slot += type.getSlots();
}
+ // Shared scope calls disabled in optimistic world. TODO is this right?
method.dynamicCall(returnType, 2 + paramTypes.length, flags);
}
@@ -179,17 +184,16 @@ class SharedScopeCall {
final Type[] params = new Type[paramTypes.length + 2];
params[0] = Type.typeFor(ScriptObject.class);
params[1] = Type.INT;
- int i = 2;
- for (Type type : paramTypes) {
- if (type.isObject()) {
- type = Type.OBJECT;
- }
- params[i++] = type;
- }
+ System.arraycopy(paramTypes, 0, params, 2, paramTypes.length);
staticSignature = Type.getMethodDescriptor(returnType, params);
}
}
return staticSignature;
}
+ @Override
+ public String toString() {
+ return methodName + " " + staticSignature;
+ }
+
}
diff --git a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
index 1339d873..40d12dfb 100644
--- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
@@ -27,7 +27,7 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
-import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
import java.util.LinkedHashSet;
import java.util.List;
@@ -35,10 +35,11 @@ import java.util.Set;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.scripts.JO;
@@ -46,21 +47,16 @@ import jdk.nashorn.internal.scripts.JO;
/**
* An object creator that uses spill properties.
*/
-public class SpillObjectCreator extends ObjectCreator {
-
- private final List<Expression> values;
+public final class SpillObjectCreator extends ObjectCreator<Expression> {
/**
* Constructor
*
* @param codegen code generator
- * @param keys keys for fields in object
- * @param symbols symbols for fields in object
- * @param values list of values corresponding to keys
+ * @param tuples tuples for key, symbol, value
*/
- protected SpillObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<Expression> values) {
- super(codegen, keys, symbols, false, false);
- this.values = values;
+ SpillObjectCreator(final CodeGenerator codegen, final List<MapTuple<Expression>> tuples) {
+ super(codegen, tuples, false, false);
makeMap();
}
@@ -68,82 +64,123 @@ public class SpillObjectCreator extends ObjectCreator {
protected void makeObject(final MethodEmitter method) {
assert !isScope() : "spill scope objects are not currently supported";
- final int length = keys.size();
- final Object[] presetValues = new Object[length];
+ final int length = tuples.size();
+ final long[] jpresetValues = new long[ScriptObject.spillAllocationLength(length)];
+ final Object[] opresetValues = new Object[ScriptObject.spillAllocationLength(length)];
final Set<Integer> postsetValues = new LinkedHashSet<>();
final int callSiteFlags = codegen.getCallSiteFlags();
- ArrayData arrayData = ArrayData.allocate(new Object[0]);
+ ArrayData arrayData = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
// Compute constant property values
- for (int i = 0; i < length; i++) {
- final String key = keys.get(i);
- final Expression value = values.get(i);
-
- if (value == null) {
- continue; // getter or setter
- }
-
- final Object constantValue = LiteralNode.objectAsConstant(value);
- if (constantValue == LiteralNode.POSTSET_MARKER) {
- postsetValues.add(i);
- continue;
- }
-
- final Property property = propertyMap.findProperty(key);
- if (property != null) {
- // normal property key
- presetValues[property.getSlot()] = constantValue;
- } else {
- // array index key
- final long oldLength = arrayData.length();
- final int index = ArrayIndex.getArrayIndex(key);
- assert ArrayIndex.isValidArrayIndex(index);
- final long longIndex = ArrayIndex.toLongIndex(index);
- if (longIndex >= oldLength) {
- arrayData = arrayData.ensure(longIndex);
- }
- arrayData = arrayData.set(index, constantValue, false);
- if (longIndex > oldLength) {
- arrayData = arrayData.delete(oldLength, longIndex - 1);
+ int pos = 0;
+ for (final MapTuple<Expression> tuple : tuples) {
+ final String key = tuple.key;
+ final Expression value = tuple.value;
+
+ //this is a nop of tuple.key isn't e.g. "apply" or another special name
+ method.invalidateSpecialName(tuple.key);
+
+ if (value != null) {
+ final Object constantValue = LiteralNode.objectAsConstant(value);
+ if (constantValue == LiteralNode.POSTSET_MARKER) {
+ postsetValues.add(pos);
+ } else {
+ final Property property = propertyMap.findProperty(key);
+ if (property != null) {
+ // normal property key
+ property.setType(JSType.unboxedFieldType(constantValue));
+ final int slot = property.getSlot();
+ if (!OBJECT_FIELDS_ONLY && constantValue instanceof Number) {
+ jpresetValues[slot] = ObjectClassGenerator.pack((Number)constantValue);
+ } else {
+ opresetValues[slot] = constantValue;
+ }
+ } else {
+ // array index key
+ final long oldLength = arrayData.length();
+ final int index = ArrayIndex.getArrayIndex(key);
+ final long longIndex = ArrayIndex.toLongIndex(index);
+
+ assert ArrayIndex.isValidArrayIndex(index);
+
+ if (longIndex >= oldLength) {
+ arrayData = arrayData.ensure(longIndex);
+ }
+
+ //avoid blowing up the array if we can
+ if (constantValue instanceof Integer) {
+ arrayData = arrayData.set(index, ((Integer)constantValue).intValue(), false);
+ } else if (constantValue instanceof Long) {
+ arrayData = arrayData.set(index, ((Long)constantValue).longValue(), false);
+ } else if (constantValue instanceof Double) {
+ arrayData = arrayData.set(index, ((Double)constantValue).doubleValue(), false);
+ } else {
+ arrayData = arrayData.set(index, constantValue, false);
+ }
+
+ if (longIndex > oldLength) {
+ arrayData = arrayData.delete(oldLength, longIndex - 1);
+ }
+ }
}
}
+ pos++;
}
+ //assert postsetValues.isEmpty() : "test me " + postsetValues;
+
// create object and invoke constructor
method._new(JO.class).dup();
codegen.loadConstant(propertyMap);
- method.invoke(constructorNoLookup(JO.class, PropertyMap.class));
- // Set spill array with preset values
- method.dup();
- codegen.loadConstant(presetValues);
- method.putField(Type.getInternalName(ScriptObject.class), "spill", Type.OBJECT_ARRAY.getDescriptor());
+ //load primitive values to j spill array
+ codegen.loadConstant(jpresetValues);
+ for (final int i : postsetValues) {
+ final MapTuple<Expression> tuple = tuples.get(i);
+ final Property property = propertyMap.findProperty(tuple.key);
+ if (property != null && tuple.isPrimitive()) {
+ method.dup();
+ method.load(property.getSlot());
+ loadTuple(method, tuple);
+ method.arraystore();
+ }
+ }
- // Set array data if any
+ //load object values to o spill array
+ codegen.loadConstant(opresetValues);
+ for (final int i : postsetValues) {
+ final MapTuple<Expression> tuple = tuples.get(i);
+ final Property property = propertyMap.findProperty(tuple.key);
+ if (property != null && !tuple.isPrimitive()) {
+ method.dup();
+ method.load(property.getSlot());
+ loadTuple(method, tuple);
+ method.arraystore();
+ }
+ }
+
+ //instantiate the script object with spill objects
+ method.invoke(constructorNoLookup(JO.class, PropertyMap.class, long[].class, Object[].class));
+
+ // Set prefix array data if any
if (arrayData.length() > 0) {
method.dup();
codegen.loadConstant(arrayData);
- method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray",void.class, ArrayData.class));
+ method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
}
- // Create properties with non-constant values
- for (int i : postsetValues) {
- final String key = keys.get(i);
- final Property property = propertyMap.findProperty(key);
-
+ // set postfix
+ for (final int i : postsetValues) {
+ final MapTuple<Expression> tuple = tuples.get(i);
+ final Property property = propertyMap.findProperty(tuple.key);
if (property == null) {
- final int index = ArrayIndex.getArrayIndex(key);
+ final int index = ArrayIndex.getArrayIndex(tuple.key);
assert ArrayIndex.isValidArrayIndex(index);
method.dup();
method.load(ArrayIndex.toLongIndex(index));
- codegen.load(values.get(i));
+ //method.println("putting " + tuple + " into arraydata");
+ loadTuple(method, tuple);
method.dynamicSetIndex(callSiteFlags);
- } else {
- method.dup();
- method.getField(Type.getInternalName(ScriptObject.class), "spill", Type.OBJECT_ARRAY.getDescriptor());
- method.load(property.getSlot());
- codegen.load(values.get(i), OBJECT);
- method.arraystore();
}
}
}
@@ -151,14 +188,12 @@ public class SpillObjectCreator extends ObjectCreator {
@Override
protected PropertyMap makeMap() {
assert propertyMap == null : "property map already initialized";
-
- propertyMap = new MapCreator(JO.class, keys, symbols) {
- @Override
- protected int getPropertyFlags(Symbol symbol, boolean hasArguments) {
- return super.getPropertyFlags(symbol, hasArguments) | Property.IS_SPILL | Property.IS_ALWAYS_OBJECT;
- }
- }.makeSpillMap(false);
-
+ propertyMap = new MapCreator<>(JO.class, tuples).makeSpillMap(false);
return propertyMap;
}
+
+ @Override
+ protected void loadValue(final Expression expr, final Type type) {
+ codegen.loadExpressionAsType(expr, type);
+ }
}
diff --git a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
new file mode 100644
index 00000000..9933274d
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.ir.Node.NO_FINISH;
+import static jdk.nashorn.internal.ir.Node.NO_LINE_NUMBER;
+import static jdk.nashorn.internal.ir.Node.NO_TOKEN;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.List;
+import java.util.Objects;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BlockLexicalContext;
+import jdk.nashorn.internal.ir.BreakNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.CaseNode;
+import jdk.nashorn.internal.ir.ContinueNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.GetSplitState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.SetSplitState;
+import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.SplitReturn;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
+
+/**
+ * A node visitor that replaces {@link SplitNode}s with anonymous function invocations and some additional constructs
+ * to support control flow across splits. By using this transformation, split functions are translated into ordinary
+ * JavaScript functions with nested anonymous functions. The transformations however introduce several AST nodes that
+ * have no JavaScript source representations ({@link GetSplitState}, {@link SetSplitState}, and {@link SplitReturn}),
+ * and therefore such function is no longer reparseable from its source. For that reason, split functions and their
+ * fragments are serialized in-memory and deserialized when they need to be recompiled either for deoptimization or
+ * for type specialization.
+ * NOTE: all {@code leave*()} methods for statements are returning their input nodes. That way, they will not mutate
+ * the original statement list in the block containing the statement, which is fine, as it'll be replaced by the
+ * lexical context when the block is left. If we returned something else (e.g. null), we'd cause a mutation in the
+ * enclosing block's statement list that is otherwise overwritten later anyway.
+ */
+final class SplitIntoFunctions extends NodeVisitor<BlockLexicalContext> {
+ private static final int FALLTHROUGH_STATE = -1;
+ private static final int RETURN_STATE = 0;
+ private static final int BREAK_STATE = 1;
+ private static final int FIRST_JUMP_STATE = 2;
+
+ private static final String THIS_NAME = CompilerConstants.THIS.symbolName();
+ private static final String RETURN_NAME = CompilerConstants.RETURN.symbolName();
+ // Used as the name of the formal parameter for passing the current value of :return symbol into a split fragment.
+ private static final String RETURN_PARAM_NAME = RETURN_NAME + "-in";
+
+ private final Deque<FunctionState> functionStates = new ArrayDeque<>();
+ private final Deque<SplitState> splitStates = new ArrayDeque<>();
+ private final Namespace namespace;
+
+ private boolean artificialBlock = false;
+
+ // -1 is program; we need to use negative ones
+ private int nextFunctionId = -2;
+
+ public SplitIntoFunctions(final Compiler compiler) {
+ super(new BlockLexicalContext() {
+ @Override
+ protected Block afterSetStatements(Block block) {
+ for(Statement stmt: block.getStatements()) {
+ assert !(stmt instanceof SplitNode);
+ }
+ return block;
+ }
+ });
+ namespace = new Namespace(compiler.getScriptEnvironment().getNamespace());
+ }
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ functionStates.push(new FunctionState(functionNode));
+ return true;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ functionStates.pop();
+ return functionNode;
+ }
+
+ @Override
+ protected Node leaveDefault(final Node node) {
+ if (node instanceof Statement) {
+ appendStatement((Statement)node);
+ }
+ return node;
+ }
+
+ @Override
+ public boolean enterSplitNode(final SplitNode splitNode) {
+ getCurrentFunctionState().splitDepth++;
+ splitStates.push(new SplitState(splitNode));
+ return true;
+ }
+
+ @Override
+ public Node leaveSplitNode(final SplitNode splitNode) {
+ // Replace the split node with an anonymous function expression call.
+
+ final FunctionState fnState = getCurrentFunctionState();
+
+ final String name = splitNode.getName();
+ Block body = splitNode.getBody();
+ final int firstLineNumber = body.getFirstStatementLineNumber();
+ final long token = body.getToken();
+ final int finish = body.getFinish();
+
+ final FunctionNode originalFn = fnState.fn;
+ assert originalFn == lc.getCurrentFunction();
+ final boolean isProgram = originalFn.isProgram();
+
+ // Change SplitNode({...}) into "function () { ... }", or "function (:return-in) () { ... }" (for program)
+ final long newFnToken = Token.toDesc(TokenType.FUNCTION, nextFunctionId--, 0);
+ final FunctionNode fn = new FunctionNode(
+ originalFn.getSource(),
+ body.getFirstStatementLineNumber(),
+ newFnToken,
+ finish,
+ NO_TOKEN,
+ namespace,
+ createIdent(name),
+ originalFn.getName() + "$" + name,
+ isProgram ? Collections.singletonList(createReturnParamIdent()) : Collections.<IdentNode>emptyList(),
+ FunctionNode.Kind.NORMAL,
+ // We only need IS_SPLIT conservatively, in case it contains any array units so that we force
+ // the :callee's existence, to force :scope to never be in a slot lower than 2. This is actually
+ // quite a horrible hack to do with CodeGenerator.fixScopeSlot not trampling other parameters
+ // and should go away once we no longer have array unit handling in codegen. Note however that
+ // we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE.
+ FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT
+ )
+ .setBody(lc, body)
+ .setCompileUnit(lc, splitNode.getCompileUnit())
+ .copyCompilationState(lc, originalFn);
+
+ // Call the function:
+ // either "(function () { ... }).call(this)"
+ // or "(function (:return-in) { ... }).call(this, :return)"
+ // NOTE: Function.call() has optimized linking that basically does a pass-through to the function being invoked.
+ // NOTE: CompilationPhase.PROGRAM_POINT_PHASE happens after this, so these calls are subject to optimistic
+ // assumptions on their return value (when they return a value), as they should be.
+ final IdentNode thisIdent = createIdent(THIS_NAME);
+ final CallNode callNode = new CallNode(firstLineNumber, token, finish, new AccessNode(NO_TOKEN, NO_FINISH, fn, "call"),
+ isProgram ? Arrays.<Expression>asList(thisIdent, createReturnIdent())
+ : Collections.<Expression>singletonList(thisIdent),
+ false);
+
+ final SplitState splitState = splitStates.pop();
+ fnState.splitDepth--;
+
+ final Expression callWithReturn;
+ final boolean hasReturn = splitState.hasReturn;
+ if (hasReturn && fnState.splitDepth > 0) {
+ final SplitState parentSplit = splitStates.peek();
+ if (parentSplit != null) {
+ // Propagate hasReturn to parent split
+ parentSplit.hasReturn = true;
+ }
+ }
+ if (hasReturn || isProgram) {
+ // capture return value: ":return = (function () { ... })();"
+ callWithReturn = new BinaryNode(Token.recast(token, TokenType.ASSIGN), createReturnIdent(), callNode);
+ } else {
+ // no return value, just call : "(function () { ... })();"
+ callWithReturn = callNode;
+ }
+ appendStatement(new ExpressionStatement(firstLineNumber, token, finish, callWithReturn));
+
+ Statement splitStateHandler;
+
+ final List<JumpStatement> jumpStatements = splitState.jumpStatements;
+ final int jumpCount = jumpStatements.size();
+ // There are jumps (breaks or continues) that need to be propagated outside the split node. We need to
+ // set up a switch statement for them:
+ // switch(:scope.getScopeState()) { ... }
+ if (jumpCount > 0) {
+ final List<CaseNode> cases = new ArrayList<>(jumpCount + (hasReturn ? 1 : 0));
+ if (hasReturn) {
+ // If the split node also contained a return, we'll slip it as a case in the switch statement
+ addCase(cases, RETURN_STATE, createReturnFromSplit());
+ }
+ int i = FIRST_JUMP_STATE;
+ for (final JumpStatement jump: jumpStatements) {
+ addCase(cases, i++, enblockAndVisit(jump));
+ }
+ splitStateHandler = new SwitchNode(NO_LINE_NUMBER, token, finish, GetSplitState.INSTANCE, cases, null);
+ } else {
+ splitStateHandler = null;
+ }
+
+ // As the switch statement itself is breakable, an unlabelled break can't be in the switch statement,
+ // so we need to test for it separately.
+ if (splitState.hasBreak) {
+ // if(:scope.getScopeState() == Scope.BREAK) { break; }
+ splitStateHandler = makeIfStateEquals(firstLineNumber, token, finish, BREAK_STATE,
+ enblockAndVisit(new BreakNode(NO_LINE_NUMBER, token, finish, null)), splitStateHandler);
+ }
+
+ // Finally, if the split node had a return statement, but there were no external jumps, we didn't have
+ // the switch statement to handle the return, so we need a separate if for it.
+ if (hasReturn && jumpCount == 0) {
+ // if (:scope.getScopeState() == Scope.RETURN) { return :return; }
+ splitStateHandler = makeIfStateEquals(NO_LINE_NUMBER, token, finish, RETURN_STATE,
+ createReturnFromSplit(), splitStateHandler);
+ }
+
+ if (splitStateHandler != null) {
+ appendStatement(splitStateHandler);
+ }
+
+ return splitNode;
+ }
+
+ private static void addCase(final List<CaseNode> cases, final int i, final Block body) {
+ cases.add(new CaseNode(NO_TOKEN, NO_FINISH, intLiteral(i), body));
+ }
+
+ private static LiteralNode<Number> intLiteral(final int i) {
+ return LiteralNode.newInstance(NO_TOKEN, NO_FINISH, i);
+ }
+
+ private static Block createReturnFromSplit() {
+ return new Block(NO_TOKEN, NO_FINISH, createReturnReturn());
+ }
+
+ private static ReturnNode createReturnReturn() {
+ return new ReturnNode(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH, createReturnIdent());
+ }
+
+ private static IdentNode createReturnIdent() {
+ return createIdent(RETURN_NAME);
+ }
+
+ private static IdentNode createReturnParamIdent() {
+ return createIdent(RETURN_PARAM_NAME);
+ }
+
+ private static IdentNode createIdent(final String name) {
+ return new IdentNode(NO_TOKEN, NO_FINISH, name);
+ }
+
+ private Block enblockAndVisit(final JumpStatement jump) {
+ artificialBlock = true;
+ final Block block = (Block)new Block(NO_TOKEN, NO_FINISH, jump).accept(this);
+ artificialBlock = false;
+ return block;
+ }
+
+ private static IfNode makeIfStateEquals(final int lineNumber, final long token, final int finish,
+ final int value, final Block pass, final Statement fail) {
+ return new IfNode(lineNumber, token, finish,
+ new BinaryNode(Token.recast(token, TokenType.EQ_STRICT),
+ GetSplitState.INSTANCE, intLiteral(value)),
+ pass,
+ fail == null ? null : new Block(NO_TOKEN, NO_FINISH, fail));
+ }
+
+ @Override
+ public boolean enterVarNode(VarNode varNode) {
+ if (!inSplitNode()) {
+ return super.enterVarNode(varNode);
+ }
+ assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
+
+ final Expression init = varNode.getInit();
+ if (varNode.isAnonymousFunctionDeclaration()) {
+ // We ain't moving anonymous function declarations.
+ return super.enterVarNode(varNode);
+ }
+
+ // Move a declaration-only var statement to the top of the outermost function.
+ getCurrentFunctionState().varStatements.add(varNode.setInit(null));
+ // If it had an initializer, replace it with an assignment expression statement. Note that "var" is a
+ // statement, so it doesn't contribute to :return of the programs, therefore we are _not_ adding a
+ // ":return = ..." assignment around the original assignment.
+ if (init != null) {
+ final long token = Token.recast(varNode.getToken(), TokenType.ASSIGN);
+ new ExpressionStatement(varNode.getLineNumber(), token, varNode.getFinish(),
+ new BinaryNode(token, varNode.getName(), varNode.getInit())).accept(this);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Node leaveBlock(final Block block) {
+ if (!artificialBlock) {
+ if (lc.isFunctionBody()) {
+ // Prepend declaration-only var statements to the top of the statement list.
+ lc.prependStatements(getCurrentFunctionState().varStatements);
+ } else if (lc.isSplitBody()) {
+ appendSplitReturn(FALLTHROUGH_STATE, NO_LINE_NUMBER);
+ if (getCurrentFunctionState().fn.isProgram()) {
+ // If we're splitting the program, make sure every shard ends with "return :return" and
+ // begins with ":return = :return-in;".
+ lc.prependStatement(new ExpressionStatement(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH,
+ new BinaryNode(Token.toDesc(TokenType.ASSIGN, 0, 0), createReturnIdent(), createReturnParamIdent())));
+ }
+ }
+ }
+ return block;
+ }
+
+ @Override
+ public Node leaveBreakNode(final BreakNode breakNode) {
+ return leaveJumpNode(breakNode);
+ }
+
+ @Override
+ public Node leaveContinueNode(final ContinueNode continueNode) {
+ return leaveJumpNode(continueNode);
+ }
+
+ private JumpStatement leaveJumpNode(final JumpStatement jump) {
+ if (inSplitNode()) {
+ final SplitState splitState = getCurrentSplitState();
+ final SplitNode splitNode = splitState.splitNode;
+ if (lc.isExternalTarget(splitNode, jump.getTarget(lc))) {
+ appendSplitReturn(splitState.getSplitStateIndex(jump), jump.getLineNumber());
+ return jump;
+ }
+ }
+ appendStatement(jump);
+ return jump;
+ }
+
+ private void appendSplitReturn(final int splitState, final int lineNumber) {
+ appendStatement(new SetSplitState(splitState, lineNumber));
+ if (getCurrentFunctionState().fn.isProgram()) {
+ // If we're splitting the program, make sure every fragment passes back :return
+ appendStatement(createReturnReturn());
+ } else {
+ appendStatement(SplitReturn.INSTANCE);
+ }
+ }
+
+ @Override
+ public Node leaveReturnNode(final ReturnNode returnNode) {
+ if(inSplitNode()) {
+ appendStatement(new SetSplitState(RETURN_STATE, returnNode.getLineNumber()));
+ getCurrentSplitState().hasReturn = true;
+ }
+ appendStatement(returnNode);
+ return returnNode;
+ }
+
+ private void appendStatement(final Statement statement) {
+ lc.appendStatement(statement);
+ }
+
+ private boolean inSplitNode() {
+ return getCurrentFunctionState().splitDepth > 0;
+ }
+
+ private FunctionState getCurrentFunctionState() {
+ return functionStates.peek();
+ }
+
+ private SplitState getCurrentSplitState() {
+ return splitStates.peek();
+ }
+
+ private static class FunctionState {
+ final FunctionNode fn;
+ final List<Statement> varStatements = new ArrayList<>();
+ int splitDepth;
+
+ FunctionState(final FunctionNode fn) {
+ this.fn = fn;
+ }
+ }
+
+ private static class SplitState {
+ final SplitNode splitNode;
+ boolean hasReturn;
+ boolean hasBreak;
+
+ final List<JumpStatement> jumpStatements = new ArrayList<>();
+
+ int getSplitStateIndex(final JumpStatement jump) {
+ if (jump instanceof BreakNode && jump.getLabelName() == null) {
+ // Unlabelled break is a special case
+ hasBreak = true;
+ return BREAK_STATE;
+ }
+
+ int i = 0;
+ for(final JumpStatement exJump: jumpStatements) {
+ if (jump.getClass() == exJump.getClass() && Objects.equals(jump.getLabelName(), exJump.getLabelName())) {
+ return i + FIRST_JUMP_STATE;
+ }
+ ++i;
+ }
+ jumpStatements.add(jump);
+ return i + FIRST_JUMP_STATE;
+ }
+
+ SplitState(final SplitNode splitNode) {
+ this.splitNode = splitNode;
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java b/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
deleted file mode 100644
index e689820f..00000000
--- a/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.SplitNode;
-import jdk.nashorn.internal.runtime.Scope;
-
-/**
- * Emitter used for splitting methods. Needs to keep track of if there are jump targets
- * outside the current split node. All external jump targets encountered at method
- * emission are logged, and {@code CodeGenerator#leaveSplitNode(SplitNode)} creates
- * an appropriate jump table when the SplitNode has been iterated through
- */
-public class SplitMethodEmitter extends MethodEmitter {
-
- private final SplitNode splitNode;
-
- private final List<Label> externalTargets = new ArrayList<>();
-
- SplitMethodEmitter(final ClassEmitter classEmitter, final MethodVisitor mv, SplitNode splitNode) {
- super(classEmitter, mv);
- this.splitNode = splitNode;
- }
-
- @Override
- void splitAwareGoto(final LexicalContext lc, final Label label) {
- assert splitNode != null;
- final int index = findExternalTarget(lc, label);
- if (index >= 0) {
- loadCompilerConstant(SCOPE);
- checkcast(Scope.class);
- load(index + 1);
- invoke(Scope.SET_SPLIT_STATE);
- loadUndefined(Type.OBJECT);
- _return(functionNode.getReturnType());
- return;
- }
- super.splitAwareGoto(lc, label);
- }
-
- private int findExternalTarget(final LexicalContext lc, final Label label) {
- final int index = externalTargets.indexOf(label);
-
- if (index >= 0) {
- return index;
- }
-
- if (lc.isExternalTarget(splitNode, label)) {
- externalTargets.add(label);
- return externalTargets.size() - 1;
- }
- return -1;
- }
-
- @Override
- MethodEmitter registerReturn() {
- setHasReturn();
- loadCompilerConstant(SCOPE);
- checkcast(Scope.class);
- load(0);
- invoke(Scope.SET_SPLIT_STATE);
- return this;
- }
-
- @Override
- final List<Label> getExternalTargets() {
- return externalTargets;
- }
-}
diff --git a/src/jdk/nashorn/internal/codegen/Splitter.java b/src/jdk/nashorn/internal/codegen/Splitter.java
index 19338499..9405d062 100644
--- a/src/jdk/nashorn/internal/codegen/Splitter.java
+++ b/src/jdk/nashorn/internal/codegen/Splitter.java
@@ -42,7 +42,7 @@ import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.options.Options;
/**
@@ -64,7 +64,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
/** Weight threshold for when to start a split. */
public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024);
- private static final DebugLogger LOG = Compiler.LOG;
+ private final DebugLogger log;
/**
* Constructor.
@@ -78,30 +78,27 @@ final class Splitter extends NodeVisitor<LexicalContext> {
this.compiler = compiler;
this.outermost = functionNode;
this.outermostCompileUnit = outermostCompileUnit;
+ this.log = compiler.getLogger();
}
/**
- * Execute the split
+ * Execute the split.
+ * @param fn the function to split
+ * @param top whether this is the topmost compiled function (it's either a program, or we're doing a recompilation).
*/
- FunctionNode split(final FunctionNode fn) {
+ FunctionNode split(final FunctionNode fn, final boolean top) {
FunctionNode functionNode = fn;
- if (functionNode.isLazy()) {
- LOG.finest("Postponing split of '", functionNode.getName(), "' as it's lazy");
- return functionNode;
- }
-
- LOG.finest("Initiating split of '", functionNode.getName(), "'");
+ log.finest("Initiating split of '", functionNode.getName(), "'");
long weight = WeighNodes.weigh(functionNode);
- final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost;
// We know that our LexicalContext is empty outside the call to functionNode.accept(this) below,
// so we can pass null to all methods expecting a LexicalContext parameter.
assert lc.isEmpty() : "LexicalContext not empty";
if (weight >= SPLIT_THRESHOLD) {
- LOG.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
+ log.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
functionNode = (FunctionNode)functionNode.accept(this);
if (functionNode.isSplit()) {
@@ -138,7 +135,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
@Override
public Node leaveFunctionNode(final FunctionNode nestedFunction) {
- FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction);
+ final FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction, false);
lc.replace(nestedFunction, split);
return split;
}
@@ -310,7 +307,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
units.add(new ArrayUnit(unit, lo, postsets.length));
}
- arrayLiteralNode.setUnits(units);
+ return arrayLiteralNode.setUnits(lc, units);
}
return literal;
@@ -319,10 +316,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
@Override
public boolean enterFunctionNode(final FunctionNode node) {
//only go into the function node for this splitter. any subfunctions are rejected
- if (node == outermost && !node.isLazy()) {
- return true;
- }
- return false;
+ return node == outermost;
}
}
diff --git a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
new file mode 100644
index 00000000..d5282a8b
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.Property.NOT_CONFIGURABLE;
+import static jdk.nashorn.internal.runtime.Property.NOT_ENUMERABLE;
+import static jdk.nashorn.internal.runtime.Property.NOT_WRITABLE;
+
+import java.lang.invoke.MethodType;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.objects.ArrayBufferView;
+import jdk.nashorn.internal.objects.NativeArray;
+import jdk.nashorn.internal.runtime.FindProperty;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Functionality for using a runtime scope to look up value types.
+ * Used during recompilation.
+ */
+final class TypeEvaluator {
+ /**
+ * Type signature for invocation of functions without parameters: we must pass (callee, this) of type
+ * (ScriptFunction, Object) respectively. We also use Object as the return type (we must pass something,
+ * but it'll be ignored; it can't be void, though).
+ */
+ private static final MethodType EMPTY_INVOCATION_TYPE = MethodType.methodType(Object.class, ScriptFunction.class, Object.class);
+
+ private final Compiler compiler;
+ private final ScriptObject runtimeScope;
+
+ TypeEvaluator(final Compiler compiler, final ScriptObject runtimeScope) {
+ this.compiler = compiler;
+ this.runtimeScope = runtimeScope;
+ }
+
+ /**
+ * Returns true if the expression can be safely evaluated, and its value is an object known to always use
+ * String as the type of its property names retrieved through
+ * {@link ScriptRuntime#toPropertyIterator(Object)}. It is used to avoid optimistic assumptions about its
+ * property name types.
+ * @param expr the expression to test
+ * @return true if the expression can be safely evaluated, and its value is an object known to always use
+ * String as the type of its property iterators.
+ */
+ boolean hasStringPropertyIterator(final Expression expr) {
+ return evaluateSafely(expr) instanceof ScriptObject;
+ }
+
+ Type getOptimisticType(final Optimistic node) {
+ assert compiler.useOptimisticTypes();
+
+ final int programPoint = node.getProgramPoint();
+ final Type validType = compiler.getInvalidatedProgramPointType(programPoint);
+
+ if (validType != null) {
+ return validType;
+ }
+
+ final Type mostOptimisticType = node.getMostOptimisticType();
+ final Type evaluatedType = getEvaluatedType(node);
+
+ if (evaluatedType != null) {
+ if (evaluatedType.widerThan(mostOptimisticType)) {
+ final Type newValidType = evaluatedType.isObject() || evaluatedType.isBoolean() ? Type.OBJECT : evaluatedType;
+ // Update invalidatedProgramPoints so we don't re-evaluate the expression next time. This is a heuristic
+ // as we're doing a tradeoff. Re-evaluating expressions on each recompile takes time, but it might
+ // notice a widening in the type of the expression and thus prevent an unnecessary deoptimization later.
+ // We'll presume though that the types of expressions are mostly stable, so if we evaluated it in one
+ // compilation, we'll keep to that and risk a low-probability deoptimization if its type gets widened
+ // in the future.
+ compiler.addInvalidatedProgramPoint(node.getProgramPoint(), newValidType);
+ }
+ return evaluatedType;
+ }
+ return mostOptimisticType;
+ }
+
+ private static Type getPropertyType(final ScriptObject sobj, final String name) {
+ final FindProperty find = sobj.findProperty(name, true);
+ if (find == null) {
+ return null;
+ }
+
+ final Property property = find.getProperty();
+ final Class<?> propertyClass = property.getType();
+ if (propertyClass == null) {
+ // propertyClass == null means its value is Undefined. It is probably not initialized yet, so we won't make
+ // a type assumption yet.
+ return null;
+ } else if (propertyClass.isPrimitive()) {
+ return Type.typeFor(propertyClass);
+ }
+
+ final ScriptObject owner = find.getOwner();
+ if (property.hasGetterFunction(owner)) {
+ // Can have side effects, so we can't safely evaluate it; since !propertyClass.isPrimitive(), it's Object.
+ return Type.OBJECT;
+ }
+
+ // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed
+ // integer).
+ final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getObjectValue(owner, owner);
+ if (value == ScriptRuntime.UNDEFINED) {
+ return null;
+ }
+ return Type.typeFor(JSType.unboxedFieldType(value));
+ }
+
+ /**
+ * Declares a symbol name as belonging to a non-scoped local variable during an on-demand compilation of a single
+ * function. This method will add an explicit Undefined binding for the local into the runtime scope if it's
+ * otherwise implicitly undefined so that when an expression is evaluated for the name, it won't accidentally find
+ * an unrelated value higher up the scope chain. It is only required to call this method when doing an optimistic
+ * on-demand compilation.
+ * @param symbolName the name of the symbol that is to be declared as being a non-scoped local variable.
+ */
+ void declareLocalSymbol(final String symbolName) {
+ assert
+ compiler.useOptimisticTypes() &&
+ compiler.isOnDemandCompilation() &&
+ runtimeScope != null :
+ "useOptimistic=" +
+ compiler.useOptimisticTypes() +
+ " isOnDemand=" +
+ compiler.isOnDemandCompilation() +
+ " scope="+runtimeScope;
+
+ if (runtimeScope.findProperty(symbolName, false) == null) {
+ runtimeScope.addOwnProperty(symbolName, NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE, ScriptRuntime.UNDEFINED);
+ }
+ }
+
+ private Object evaluateSafely(final Expression expr) {
+ if (expr instanceof IdentNode) {
+ return runtimeScope == null ? null : evaluatePropertySafely(runtimeScope, ((IdentNode)expr).getName());
+ }
+
+ if (expr instanceof AccessNode) {
+ final AccessNode accessNode = (AccessNode)expr;
+ final Object base = evaluateSafely(accessNode.getBase());
+ if (!(base instanceof ScriptObject)) {
+ return null;
+ }
+ return evaluatePropertySafely((ScriptObject)base, accessNode.getProperty());
+ }
+
+ return null;
+ }
+
+ private static Object evaluatePropertySafely(final ScriptObject sobj, final String name) {
+ final FindProperty find = sobj.findProperty(name, true);
+ if (find == null) {
+ return null;
+ }
+ final Property property = find.getProperty();
+ final ScriptObject owner = find.getOwner();
+ if (property.hasGetterFunction(owner)) {
+ // Possible side effects; can't evaluate safely
+ return null;
+ }
+ return property.getObjectValue(owner, owner);
+ }
+
+
+ private Type getEvaluatedType(final Optimistic expr) {
+ if (expr instanceof IdentNode) {
+ if (runtimeScope == null) {
+ return null;
+ }
+ return getPropertyType(runtimeScope, ((IdentNode)expr).getName());
+ } else if (expr instanceof AccessNode) {
+ final AccessNode accessNode = (AccessNode)expr;
+ final Object base = evaluateSafely(accessNode.getBase());
+ if (!(base instanceof ScriptObject)) {
+ return null;
+ }
+ return getPropertyType((ScriptObject)base, accessNode.getProperty());
+ } else if (expr instanceof IndexNode) {
+ final IndexNode indexNode = (IndexNode)expr;
+ final Object base = evaluateSafely(indexNode.getBase());
+ if(base instanceof NativeArray || base instanceof ArrayBufferView) {
+ // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their
+ // underlying array storage, not based on values of individual elements. Thus, a LongArrayData will
+ // throw UOE for every optimistic int linkage attempt, even if the long value being returned in the
+ // first invocation would be representable as int. That way, we can presume that the array's optimistic
+ // type is the most optimistic type for which an element getter has a chance of executing successfully.
+ return ((ScriptObject)base).getArray().getOptimisticType();
+ }
+ } else if (expr instanceof CallNode) {
+ // Currently, we'll only try to guess the return type of immediately invoked function expressions with no
+ // parameters, that is (function() { ... })(). We could do better, but these are all heuristics and we can
+ // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom.
+ final CallNode callExpr = (CallNode)expr;
+ final Expression fnExpr = callExpr.getFunction();
+ if (fnExpr instanceof FunctionNode) {
+ final FunctionNode fn = (FunctionNode)fnExpr;
+ if (callExpr.getArgs().isEmpty()) {
+ final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
+ if (data != null) {
+ final Type returnType = Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope));
+ if (returnType == Type.BOOLEAN) {
+ // We don't have optimistic booleans. In fact, optimistic call sites getting back boolean
+ // currently deoptimize all the way to Object.
+ return Type.OBJECT;
+ }
+ assert returnType == Type.INT || returnType == Type.LONG || returnType == Type.NUMBER || returnType == Type.OBJECT;
+ return returnType;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/TypeMap.java b/src/jdk/nashorn/internal/codegen/TypeMap.java
new file mode 100644
index 00000000..11efce1a
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/TypeMap.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2010-2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+
+/**
+ * A data structure that maps one or several function nodes (by their unique id:s, not by
+ * the FunctionNode object itself, due to copy on write changing it several times through
+ * code generation.
+ */
+public class TypeMap {
+ private final Map<Integer, Type[]> paramTypeMap = new HashMap<>();
+ private final Map<Integer, Type> returnTypeMap = new HashMap<>();
+ private final boolean needsCallee;
+
+ /**
+ * Constructor
+ * @param functionNodeId function node id
+ * @param type method type found at runtime corresponding to parameter guess
+ * @param needsCallee does the function using this type map need a callee
+ */
+ public TypeMap(final int functionNodeId, final MethodType type, final boolean needsCallee) {
+ final Type[] types = new Type[type.parameterCount()];
+ int pos = 0;
+ for (final Class<?> p : type.parameterArray()) {
+ types[pos++] = Type.typeFor(p);
+ }
+ paramTypeMap.put(functionNodeId, types);
+ returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType()));
+
+ this.needsCallee = needsCallee;
+ }
+
+ /**
+ * Returns the array of parameter types for a particular function node
+ * @param functionNodeId the ID of the function node
+ * @return an array of parameter types
+ * @throws NoSuchElementException if the type map has no mapping for the requested function
+ */
+ public Type[] getParameterTypes(final int functionNodeId) {
+ final Type[] paramTypes = paramTypeMap.get(functionNodeId);
+ if (paramTypes == null) {
+ throw new NoSuchElementException(Integer.toString(functionNodeId));
+ }
+ return paramTypes.clone();
+ }
+
+ MethodType getCallSiteType(final FunctionNode functionNode) {
+ final Type[] types = paramTypeMap.get(functionNode.getId());
+ if (types == null) {
+ return null;
+ }
+
+ MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass());
+ if (needsCallee) {
+ mt = mt.appendParameterTypes(ScriptFunction.class);
+ }
+
+ mt = mt.appendParameterTypes(Object.class); //this
+
+ for (final Type type : types) {
+ if (type == null) {
+ return null; // not all parameter information is supplied
+ }
+ mt = mt.appendParameterTypes(type.getTypeClass());
+ }
+
+ return mt;
+ }
+
+ /**
+ * Does the function using this TypeMap need a callee argument. This is used
+ * to compute correct param index offsets in {@link jdk.nashorn.internal.codegen.ApplySpecialization}
+ * @return true if a callee is needed, false otherwise
+ */
+ public boolean needsCallee() {
+ return needsCallee;
+ }
+
+ /**
+ * Get the parameter type for this parameter position, or
+ * null if now known
+ * @param functionNode functionNode
+ * @param pos position
+ * @return parameter type for this callsite if known
+ */
+ Type get(final FunctionNode functionNode, final int pos) {
+ final Type[] types = paramTypeMap.get(functionNode.getId());
+ assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this;
+ if (types != null && pos < types.length) {
+ return types[pos];
+ }
+ return null;
+ }
+
+ boolean has(final FunctionNode functionNode) {
+ final int id = functionNode.getId();
+ final Type[] paramTypes = paramTypeMap.get(id);
+ assert (paramTypes == null) == (returnTypeMap.get(id) == null) : "inconsistent param and return types in param map";
+ return paramTypes != null;
+ }
+
+ @Override
+ public String toString() {
+ return toString("");
+ }
+
+ String toString(final String prefix) {
+ final StringBuilder sb = new StringBuilder();
+
+ if (paramTypeMap.isEmpty()) {
+ sb.append(prefix).append("\t<empty>");
+ return sb.toString();
+ }
+
+ for (final Map.Entry<Integer, Type[]> entry : paramTypeMap.entrySet()) {
+ final int id = entry.getKey();
+ sb.append(prefix).append('\t');
+ sb.append("function ").append(id).append('\n');
+ sb.append(prefix).append("\t\tparamTypes=");
+ if (entry.getValue() == null) {
+ sb.append("[]");
+ } else {
+ sb.append(Arrays.toString(entry.getValue()));
+ }
+ sb.append('\n');
+ sb.append(prefix).append("\t\treturnType=");
+ final Type ret = returnTypeMap.get(id);
+ sb.append(ret == null ? "N/A" : ret);
+ sb.append('\n');
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/src/jdk/nashorn/internal/codegen/WeighNodes.java b/src/jdk/nashorn/internal/codegen/WeighNodes.java
index f5940488..26660a3a 100644
--- a/src/jdk/nashorn/internal/codegen/WeighNodes.java
+++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java
@@ -27,7 +27,6 @@ package jdk.nashorn.internal.codegen;
import java.util.List;
import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
@@ -69,24 +68,25 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
* Weight constants.
*/
static final long FUNCTION_WEIGHT = 40;
- static final long AASTORE_WEIGHT = 2;
- static final long ACCESS_WEIGHT = 4;
+ static final long AASTORE_WEIGHT = 2;
+ static final long ACCESS_WEIGHT = 4;
static final long ADD_WEIGHT = 10;
- static final long BREAK_WEIGHT = 1;
+ static final long BREAK_WEIGHT = 1;
static final long CALL_WEIGHT = 10;
static final long CATCH_WEIGHT = 10;
- static final long CONTINUE_WEIGHT = 1;
- static final long IF_WEIGHT = 2;
+ static final long COMPARE_WEIGHT = 6;
+ static final long CONTINUE_WEIGHT = 1;
+ static final long IF_WEIGHT = 2;
static final long LITERAL_WEIGHT = 10;
- static final long LOOP_WEIGHT = 4;
- static final long NEW_WEIGHT = 6;
+ static final long LOOP_WEIGHT = 4;
+ static final long NEW_WEIGHT = 6;
static final long FUNC_EXPR_WEIGHT = 20;
- static final long RETURN_WEIGHT = 2;
+ static final long RETURN_WEIGHT = 2;
static final long SPLIT_WEIGHT = 40;
- static final long SWITCH_WEIGHT = 8;
- static final long THROW_WEIGHT = 2;
+ static final long SWITCH_WEIGHT = 8;
+ static final long THROW_WEIGHT = 2;
static final long VAR_WEIGHT = 40;
- static final long WITH_WEIGHT = 8;
+ static final long WITH_WEIGHT = 8;
/** Accumulated weight. */
private long weight;
@@ -101,7 +101,7 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
*
* @param weightCache cache of already calculated block weights
*/
- private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) {
+ private WeighNodes(final FunctionNode topFunction, final Map<Node, Long> weightCache) {
super(new LexicalContext());
this.topFunction = topFunction;
this.weightCache = weightCache;
@@ -173,7 +173,6 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
if (functionNode == topFunction) {
// the function being weighted; descend into its statements
return true;
-// functionNode.visitStatements(this);
}
// just a reference to inner function from outer function
weight += FUNC_EXPR_WEIGHT;
@@ -307,11 +306,6 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
}
@Override
- public Node leaveDISCARD(final UnaryNode unaryNode) {
- return unaryNodeWeight(unaryNode);
- }
-
- @Override
public Node leaveNEW(final UnaryNode unaryNode) {
weight += NEW_WEIGHT;
return unaryNode;
@@ -446,22 +440,22 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveEQ(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
public Node leaveEQ_STRICT(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
public Node leaveGE(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
public Node leaveGT(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
@@ -478,12 +472,12 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveLE(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
public Node leaveLT(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
@@ -498,12 +492,12 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveNE(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
public Node leaveNE_STRICT(final BinaryNode binaryNode) {
- return runtimeNodeWeight(binaryNode);
+ return compareWeight(binaryNode);
}
@Override
@@ -546,8 +540,8 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
return unaryNode;
}
- private Node runtimeNodeWeight(final BinaryNode binaryNode) {
- weight += Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()).isObject() ? CALL_WEIGHT : 1;
+ private Node compareWeight(final BinaryNode binaryNode) {
+ weight += COMPARE_WEIGHT;
return binaryNode;
}
}
diff --git a/bin/jjs b/src/jdk/nashorn/internal/codegen/anchor.properties
index f89a07c2..1a930682 100644
--- a/bin/jjs
+++ b/src/jdk/nashorn/internal/codegen/anchor.properties
@@ -1,6 +1,5 @@
-#!/bin/bash
#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -24,6 +23,5 @@
# questions.
#
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-$JAVA_HOME/bin/java -server -XX:+TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $*
+# This file exists only so OptimisticTypesPersistence.getVersionDirName() can take its URL.
diff --git a/src/jdk/nashorn/internal/codegen/types/ArrayType.java b/src/jdk/nashorn/internal/codegen/types/ArrayType.java
index b6701df4..442e3955 100644
--- a/src/jdk/nashorn/internal/codegen/types/ArrayType.java
+++ b/src/jdk/nashorn/internal/codegen/types/ArrayType.java
@@ -37,6 +37,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor;
* This is an array type, i.e. OBJECT_ARRAY, NUMBER_ARRAY.
*/
public class ArrayType extends ObjectType implements BytecodeArrayOps {
+ private static final long serialVersionUID = 1L;
/**
* Constructor
diff --git a/src/jdk/nashorn/internal/codegen/types/BitwiseType.java b/src/jdk/nashorn/internal/codegen/types/BitwiseType.java
index dbd0aa14..45fa5276 100644
--- a/src/jdk/nashorn/internal/codegen/types/BitwiseType.java
+++ b/src/jdk/nashorn/internal/codegen/types/BitwiseType.java
@@ -29,6 +29,7 @@ package jdk.nashorn.internal.codegen.types;
* This class represents a numeric type that can be used for bit operations.
*/
public abstract class BitwiseType extends NumericType implements BytecodeBitwiseOps {
+ private static final long serialVersionUID = 1L;
/**
* Constructor
diff --git a/src/jdk/nashorn/internal/codegen/types/BooleanType.java b/src/jdk/nashorn/internal/codegen/types/BooleanType.java
index 840b2910..234dbdba 100644
--- a/src/jdk/nashorn/internal/codegen/types/BooleanType.java
+++ b/src/jdk/nashorn/internal/codegen/types/BooleanType.java
@@ -50,24 +50,29 @@
package jdk.nashorn.internal.codegen.types;
+import static jdk.internal.org.objectweb.asm.Opcodes.I2D;
+import static jdk.internal.org.objectweb.asm.Opcodes.I2L;
+import static jdk.internal.org.objectweb.asm.Opcodes.IADD;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.runtime.JSType;
/**
* The boolean type class
*/
public final class BooleanType extends Type {
+ private static final long serialVersionUID = 1L;
private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Boolean.class, "valueOf", Boolean.class, boolean.class);
+ private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Boolean.class, "toString", String.class, boolean.class);
/**
* Constructor
@@ -87,8 +92,19 @@ public final class BooleanType extends Type {
}
@Override
+ public char getBytecodeStackType() {
+ return 'I';
+ }
+
+ @Override
public Type loadUndefined(final MethodVisitor method) {
- method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_INT);
+ method.visitLdcInsn(UNDEFINED_INT);
+ return BOOLEAN;
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ method.visitInsn(ICONST_0);
return BOOLEAN;
}
@@ -124,31 +140,30 @@ public final class BooleanType extends Type {
}
if (to.isNumber()) {
- convert(method, OBJECT);
- invokeStatic(method, JSType.TO_NUMBER);
- } else if (to.isInteger()) {
- return to; // do nothing.
- } else if (to.isLong()) {
- convert(method, OBJECT);
- invokeStatic(method, JSType.TO_UINT32);
+ method.visitInsn(I2D);
} else if (to.isLong()) {
- convert(method, OBJECT);
- invokeStatic(method, JSType.TO_LONG);
+ method.visitInsn(I2L);
+ } else if (to.isInteger()) {
+ //nop
} else if (to.isString()) {
- invokeStatic(method, VALUE_OF);
- invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+ invokestatic(method, TO_STRING);
} else if (to.isObject()) {
- invokeStatic(method, VALUE_OF);
+ invokestatic(method, VALUE_OF);
} else {
- assert false : "Illegal conversion " + this + " -> " + to;
+ throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
}
return to;
}
@Override
- public Type add(final MethodVisitor method) {
- assert false : "unsupported operation";
- return null;
+ public Type add(final MethodVisitor method, final int programPoint) {
+ // Adding booleans in JavaScript is perfectly valid, they add as if false=0 and true=1
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(IADD);
+ } else {
+ method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
+ return INT;
}
}
diff --git a/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java b/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
index ae530281..91209c26 100644
--- a/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
+++ b/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
@@ -36,50 +36,55 @@ interface BytecodeNumericOps {
* Pop and negate the value on top of the stack and push the result
*
* @param method method visitor
- *
+ * @param programPoint program point id
* @return result type
*/
- Type neg(MethodVisitor method);
+ Type neg(MethodVisitor method, int programPoint);
/**
* Pop two values on top of the stack and subtract the first from the
* second, pushing the result on the stack
*
* @param method method visitor
- *
+ * @param programPoint program point id
* @return result type
*/
- Type sub(MethodVisitor method);
+ Type sub(MethodVisitor method, int programPoint);
/**
* Pop and multiply the two values on top of the stack and push the result
* on the stack
*
* @param method method visitor
- *
+ * @param programPoint program point id
* @return result type
*/
- Type mul(MethodVisitor method);
+ Type mul(MethodVisitor method, int programPoint);
/**
* Pop two values on top of the stack and divide the first with the second,
* pushing the result on the stack
*
* @param method method visitor
- *
+ * @param programPoint program point id
* @return result type
*/
- Type div(MethodVisitor method);
+ Type div(MethodVisitor method, int programPoint);
/**
* Pop two values on top of the stack and compute the modulo of the first
* with the second, pushing the result on the stack
*
- * @param method method visitor
+ * Note that the rem method never takes a program point, because it
+ * can never be more optimistic than its widest operand - an int/int
+ * rem operation or a long/long rem operation can never return a
+ * winder remainder than the int or the long
*
+ * @param method method visitor
+ * @param programPoint program point id
* @return result type
*/
- Type rem(MethodVisitor method);
+ Type rem(MethodVisitor method, int programPoint);
/**
* Comparison with int return value, e.g. LCMP, DCMP.
diff --git a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
index bbbddf94..1cfb7575 100644
--- a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
+++ b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
@@ -85,9 +85,10 @@ interface BytecodeOps {
* first to the second, pushing the result on the stack
*
* @param method method visitor
+ * @param programPoint program point id
* @return result type
*/
- Type add(MethodVisitor method);
+ Type add(MethodVisitor method, int programPoint);
/**
* Load a variable from a local slot to the stack
@@ -129,6 +130,17 @@ interface BytecodeOps {
Type loadUndefined(MethodVisitor method);
/**
+ * Load the "forced initializer" value to the stack, used to ensure that a local variable has a value when it is
+ * read by the unwarranted optimism catch block.
+ *
+ * @param method method visitor.
+ *
+ * @return the forced initialization type at the top of the stack
+ */
+ Type loadForcedInitializer(MethodVisitor method);
+
+
+ /**
* Load the "empty" value to the stack.
*
* @param method method visitor.
diff --git a/src/jdk/nashorn/internal/codegen/types/IntType.java b/src/jdk/nashorn/internal/codegen/types/IntType.java
index c282d109..43b06806 100644
--- a/src/jdk/nashorn/internal/codegen/types/IntType.java
+++ b/src/jdk/nashorn/internal/codegen/types/IntType.java
@@ -37,12 +37,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_3;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_4;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_5;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_M1;
-import static jdk.internal.org.objectweb.asm.Opcodes.IDIV;
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.IMUL;
import static jdk.internal.org.objectweb.asm.Opcodes.INEG;
import static jdk.internal.org.objectweb.asm.Opcodes.IOR;
-import static jdk.internal.org.objectweb.asm.Opcodes.IREM;
import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
import static jdk.internal.org.objectweb.asm.Opcodes.ISHL;
import static jdk.internal.org.objectweb.asm.Opcodes.ISHR;
@@ -52,15 +50,18 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IUSHR;
import static jdk.internal.org.objectweb.asm.Opcodes.IXOR;
import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.runtime.JSType;
/**
* Type class: INT
*/
class IntType extends BitwiseType {
+ private static final long serialVersionUID = 1L;
private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Integer.class, "toString", String.class, int.class);
private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Integer.class, "valueOf", Integer.class, int.class);
@@ -80,42 +81,47 @@ class IntType extends BitwiseType {
}
@Override
+ public char getBytecodeStackType() {
+ return 'I';
+ }
+
+ @Override
public Type ldc(final MethodVisitor method, final Object c) {
assert c instanceof Integer;
final int value = ((Integer) c).intValue();
switch (value) {
- case -1:
- method.visitInsn(ICONST_M1);
- break;
- case 0:
- method.visitInsn(ICONST_0);
- break;
- case 1:
- method.visitInsn(ICONST_1);
- break;
- case 2:
- method.visitInsn(ICONST_2);
- break;
- case 3:
- method.visitInsn(ICONST_3);
- break;
- case 4:
- method.visitInsn(ICONST_4);
- break;
- case 5:
- method.visitInsn(ICONST_5);
- break;
- default:
- if (value == (byte) value) {
- method.visitIntInsn(BIPUSH, value);
- } else if (value == (short) value) {
- method.visitIntInsn(SIPUSH, value);
- } else {
- method.visitLdcInsn(c);
- }
- break;
+ case -1:
+ method.visitInsn(ICONST_M1);
+ break;
+ case 0:
+ method.visitInsn(ICONST_0);
+ break;
+ case 1:
+ method.visitInsn(ICONST_1);
+ break;
+ case 2:
+ method.visitInsn(ICONST_2);
+ break;
+ case 3:
+ method.visitInsn(ICONST_3);
+ break;
+ case 4:
+ method.visitInsn(ICONST_4);
+ break;
+ case 5:
+ method.visitInsn(ICONST_5);
+ break;
+ default:
+ if (value == (byte) value) {
+ method.visitIntInsn(BIPUSH, value);
+ } else if (value == (short) value) {
+ method.visitIntInsn(SIPUSH, value);
+ } else {
+ method.visitLdcInsn(c);
+ }
+ break;
}
return Type.INT;
@@ -134,19 +140,23 @@ class IntType extends BitwiseType {
} else if (to.isBoolean()) {
//nop
} else if (to.isString()) {
- invokeStatic(method, TO_STRING);
+ invokestatic(method, TO_STRING);
} else if (to.isObject()) {
- invokeStatic(method, VALUE_OF);
+ invokestatic(method, VALUE_OF);
} else {
- assert false : "Illegal conversion " + this + " -> " + to;
+ throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
}
return to;
}
@Override
- public Type add(final MethodVisitor method) {
- method.visitInsn(IADD);
+ public Type add(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(IADD);
+ } else {
+ method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@@ -200,32 +210,52 @@ class IntType extends BitwiseType {
}
@Override
- public Type sub(final MethodVisitor method) {
- method.visitInsn(ISUB);
+ public Type sub(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(ISUB);
+ } else {
+ method.visitInvokeDynamicInsn("isub", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@Override
- public Type mul(final MethodVisitor method) {
- method.visitInsn(IMUL);
+ public Type mul(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(IMUL);
+ } else {
+ method.visitInvokeDynamicInsn("imul", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@Override
- public Type div(final MethodVisitor method) {
- method.visitInsn(IDIV);
+ public Type div(final MethodVisitor method, final int programPoint) {
+ if (programPoint == INVALID_PROGRAM_POINT) {
+ JSType.DIV_ZERO.invoke(method);
+ } else {
+ method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@Override
- public Type rem(final MethodVisitor method) {
- method.visitInsn(IREM);
+ public Type rem(final MethodVisitor method, final int programPoint) {
+ if (programPoint == INVALID_PROGRAM_POINT) {
+ JSType.REM_ZERO.invoke(method);
+ } else {
+ method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@Override
- public Type neg(final MethodVisitor method) {
- method.visitInsn(INEG);
+ public Type neg(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(INEG);
+ } else {
+ method.visitInvokeDynamicInsn("ineg", "(I)I", MATHBOOTSTRAP, programPoint);
+ }
return INT;
}
@@ -236,19 +266,24 @@ class IntType extends BitwiseType {
@Override
public Type loadUndefined(final MethodVisitor method) {
- method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_INT);
+ method.visitLdcInsn(UNDEFINED_INT);
+ return INT;
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ method.visitInsn(ICONST_0);
return INT;
}
@Override
public Type cmp(final MethodVisitor method, final boolean isCmpG) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("cmp" + (isCmpG ? 'g' : 'l'));
}
@Override
public Type cmp(final MethodVisitor method) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("cmp");
}
+
}
diff --git a/src/jdk/nashorn/internal/codegen/types/LongType.java b/src/jdk/nashorn/internal/codegen/types/LongType.java
index b57ea6d3..aa2ceb23 100644
--- a/src/jdk/nashorn/internal/codegen/types/LongType.java
+++ b/src/jdk/nashorn/internal/codegen/types/LongType.java
@@ -32,12 +32,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.LAND;
import static jdk.internal.org.objectweb.asm.Opcodes.LCMP;
import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0;
import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1;
-import static jdk.internal.org.objectweb.asm.Opcodes.LDIV;
import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.LMUL;
-import static jdk.internal.org.objectweb.asm.Opcodes.LNEG;
import static jdk.internal.org.objectweb.asm.Opcodes.LOR;
-import static jdk.internal.org.objectweb.asm.Opcodes.LREM;
import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
import static jdk.internal.org.objectweb.asm.Opcodes.LSHL;
import static jdk.internal.org.objectweb.asm.Opcodes.LSHR;
@@ -46,15 +43,18 @@ import static jdk.internal.org.objectweb.asm.Opcodes.LSUB;
import static jdk.internal.org.objectweb.asm.Opcodes.LUSHR;
import static jdk.internal.org.objectweb.asm.Opcodes.LXOR;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.runtime.JSType;
/**
* Type class: LONG
*/
class LongType extends BitwiseType {
+ private static final long serialVersionUID = 1L;
private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
@@ -77,6 +77,11 @@ class LongType extends BitwiseType {
}
@Override
+ public char getBytecodeStackType() {
+ return 'J';
+ }
+
+ @Override
public Type cmp(final MethodVisitor method) {
method.visitInsn(LCMP);
return INT;
@@ -121,11 +126,11 @@ class LongType extends BitwiseType {
if (to.isNumber()) {
method.visitInsn(L2D);
} else if (to.isInteger()) {
- method.visitInsn(L2I);
+ invokestatic(method, JSType.TO_INT32_L);
} else if (to.isBoolean()) {
method.visitInsn(L2I);
} else if (to.isObject()) {
- invokeStatic(method, VALUE_OF);
+ invokestatic(method, VALUE_OF);
} else {
assert false : "Illegal conversion " + this + " -> " + to;
}
@@ -134,32 +139,52 @@ class LongType extends BitwiseType {
}
@Override
- public Type add(final MethodVisitor method) {
- method.visitInsn(LADD);
+ public Type add(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(LADD);
+ } else {
+ method.visitInvokeDynamicInsn("ladd", "(JJ)J", MATHBOOTSTRAP, programPoint);
+ }
return LONG;
}
@Override
- public Type sub(final MethodVisitor method) {
- method.visitInsn(LSUB);
+ public Type sub(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(LSUB);
+ } else {
+ method.visitInvokeDynamicInsn("lsub", "(JJ)J", MATHBOOTSTRAP, programPoint);
+ }
return LONG;
}
@Override
- public Type mul(final MethodVisitor method) {
- method.visitInsn(LMUL);
+ public Type mul(final MethodVisitor method, final int programPoint) {
+ if(programPoint == INVALID_PROGRAM_POINT) {
+ method.visitInsn(LMUL);
+ } else {
+ method.visitInvokeDynamicInsn("lmul", "(JJ)J", MATHBOOTSTRAP, programPoint);
+ }
return LONG;
}
@Override
- public Type div(final MethodVisitor method) {
- method.visitInsn(LDIV);
+ public Type div(final MethodVisitor method, final int programPoint) {
+ if (programPoint == INVALID_PROGRAM_POINT) {
+ JSType.DIV_ZERO_LONG.invoke(method);
+ } else {
+ method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
+ }
return LONG;
}
@Override
- public Type rem(final MethodVisitor method) {
- method.visitInsn(LREM);
+ public Type rem(final MethodVisitor method, final int programPoint) {
+ if (programPoint == INVALID_PROGRAM_POINT) {
+ JSType.REM_ZERO_LONG.invoke(method);
+ } else {
+ method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
+ }
return LONG;
}
@@ -200,8 +225,8 @@ class LongType extends BitwiseType {
}
@Override
- public Type neg(final MethodVisitor method) {
- method.visitInsn(LNEG);
+ public Type neg(final MethodVisitor method, final int programPoint) {
+ method.visitInvokeDynamicInsn("lneg", "(J)J", MATHBOOTSTRAP, programPoint);
return LONG;
}
@@ -212,7 +237,13 @@ class LongType extends BitwiseType {
@Override
public Type loadUndefined(final MethodVisitor method) {
- method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_LONG);
+ method.visitLdcInsn(UNDEFINED_LONG);
+ return LONG;
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ method.visitInsn(LCONST_0);
return LONG;
}
diff --git a/src/jdk/nashorn/internal/codegen/types/NumberType.java b/src/jdk/nashorn/internal/codegen/types/NumberType.java
index 6a280b79..924880b1 100644
--- a/src/jdk/nashorn/internal/codegen/types/NumberType.java
+++ b/src/jdk/nashorn/internal/codegen/types/NumberType.java
@@ -39,13 +39,14 @@ import static jdk.internal.org.objectweb.asm.Opcodes.DRETURN;
import static jdk.internal.org.objectweb.asm.Opcodes.DSTORE;
import static jdk.internal.org.objectweb.asm.Opcodes.DSUB;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.runtime.JSType;
class NumberType extends NumericType {
+ private static final long serialVersionUID = 1L;
private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Double.class, "valueOf", Double.class, double.class);
@@ -64,6 +65,11 @@ class NumberType extends NumericType {
}
@Override
+ public char getBytecodeStackType() {
+ return 'D';
+ }
+
+ @Override
public Type cmp(final MethodVisitor method, final boolean isCmpG) {
method.visitInsn(isCmpG ? DCMPG : DCMPL);
return INT;
@@ -84,7 +90,13 @@ class NumberType extends NumericType {
@Override
public Type loadUndefined(final MethodVisitor method) {
- method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_DOUBLE);
+ method.visitLdcInsn(UNDEFINED_DOUBLE);
+ return NUMBER;
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ method.visitInsn(DCONST_0);
return NUMBER;
}
@@ -112,54 +124,54 @@ class NumberType extends NumericType {
}
if (to.isInteger()) {
- invokeStatic(method, JSType.TO_INT32_D);
+ invokestatic(method, JSType.TO_INT32_D);
} else if (to.isLong()) {
- invokeStatic(method, JSType.TO_INT64_D);
+ invokestatic(method, JSType.TO_LONG_D);
} else if (to.isBoolean()) {
- invokeStatic(method, JSType.TO_BOOLEAN_D);
+ invokestatic(method, JSType.TO_BOOLEAN_D);
} else if (to.isString()) {
- invokeStatic(method, JSType.TO_STRING_D);
+ invokestatic(method, JSType.TO_STRING_D);
} else if (to.isObject()) {
- invokeStatic(method, VALUE_OF);
+ invokestatic(method, VALUE_OF);
} else {
- assert false : "Illegal conversion " + this + " -> " + to;
+ throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
}
return to;
}
@Override
- public Type add(final MethodVisitor method) {
+ public Type add(final MethodVisitor method, final int programPoint) {
method.visitInsn(DADD);
return NUMBER;
}
@Override
- public Type sub(final MethodVisitor method) {
+ public Type sub(final MethodVisitor method, final int programPoint) {
method.visitInsn(DSUB);
return NUMBER;
}
@Override
- public Type mul(final MethodVisitor method) {
+ public Type mul(final MethodVisitor method, final int programPoint) {
method.visitInsn(DMUL);
return NUMBER;
}
@Override
- public Type div(final MethodVisitor method) {
+ public Type div(final MethodVisitor method, final int programPoint) {
method.visitInsn(DDIV);
return NUMBER;
}
@Override
- public Type rem(final MethodVisitor method) {
+ public Type rem(final MethodVisitor method, final int programPoint) {
method.visitInsn(DREM);
return NUMBER;
}
@Override
- public Type neg(final MethodVisitor method) {
+ public Type neg(final MethodVisitor method, final int programPoint) {
method.visitInsn(DNEG);
return NUMBER;
}
diff --git a/src/jdk/nashorn/internal/codegen/types/NumericType.java b/src/jdk/nashorn/internal/codegen/types/NumericType.java
index 597ff578..d536cc7d 100644
--- a/src/jdk/nashorn/internal/codegen/types/NumericType.java
+++ b/src/jdk/nashorn/internal/codegen/types/NumericType.java
@@ -29,6 +29,8 @@ package jdk.nashorn.internal.codegen.types;
* This is a numeric type, i.e. NUMBER, LONG, INT, INT32.
*/
public abstract class NumericType extends Type implements BytecodeNumericOps {
+ private static final long serialVersionUID = 1L;
+
/**
* Constructor
*
diff --git a/src/jdk/nashorn/internal/codegen/types/ObjectType.java b/src/jdk/nashorn/internal/codegen/types/ObjectType.java
index 1f7a0221..1538489e 100644
--- a/src/jdk/nashorn/internal/codegen/types/ObjectType.java
+++ b/src/jdk/nashorn/internal/codegen/types/ObjectType.java
@@ -47,6 +47,7 @@ import jdk.nashorn.internal.runtime.Undefined;
* contain a class that is a more specialized object
*/
class ObjectType extends Type {
+ private static final long serialVersionUID = 1L;
protected ObjectType() {
this(Object.class);
@@ -65,8 +66,13 @@ class ObjectType extends Type {
}
@Override
- public Type add(final MethodVisitor method) {
- invokeStatic(method, ScriptRuntime.ADD);
+ public String getShortDescriptor() {
+ return getTypeClass() == Object.class ? "Object" : getTypeClass().getSimpleName();
+ }
+
+ @Override
+ public Type add(final MethodVisitor method, final int programPoint) {
+ invokestatic(method, ScriptRuntime.ADD);
return Type.OBJECT;
}
@@ -74,7 +80,7 @@ class ObjectType extends Type {
public Type load(final MethodVisitor method, final int slot) {
assert slot != -1;
method.visitVarInsn(ALOAD, slot);
- return Type.OBJECT;
+ return this;
}
@Override
@@ -86,13 +92,21 @@ class ObjectType extends Type {
@Override
public Type loadUndefined(final MethodVisitor method) {
method.visitFieldInsn(GETSTATIC, className(ScriptRuntime.class), "UNDEFINED", typeDescriptor(Undefined.class));
+ return UNDEFINED;
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ method.visitInsn(ACONST_NULL);
+ // TODO: do we need a special type for null, e.g. Type.NULL? It should be assignable to any other object type
+ // without a checkast in convert.
return OBJECT;
}
@Override
public Type loadEmpty(final MethodVisitor method) {
method.visitFieldInsn(GETSTATIC, className(ScriptRuntime.class), "EMPTY", typeDescriptor(Undefined.class));
- return OBJECT;
+ return UNDEFINED;
}
@Override
@@ -108,10 +122,10 @@ class ObjectType extends Type {
method.visitLdcInsn(c);
return Type.typeFor(MethodHandle.class);
} else {
- assert false : "implementation missing for class " + c.getClass() + " value=" + c;
+ throw new UnsupportedOperationException("implementation missing for class " + c.getClass() + " value=" + c);
}
- return OBJECT;
+ return Type.OBJECT;
}
@Override
@@ -138,6 +152,10 @@ class ObjectType extends Type {
}
return to;
} else if (to.isObject()) {
+ final Class<?> toClass = to.getTypeClass();
+ if(!toClass.isAssignableFrom(getTypeClass())) {
+ method.visitTypeInsn(CHECKCAST, CompilerConstants.className(toClass));
+ }
return to;
}
} else if (isString()) {
@@ -145,17 +163,19 @@ class ObjectType extends Type {
}
if (to.isInteger()) {
- invokeStatic(method, JSType.TO_INT32);
+ invokestatic(method, JSType.TO_INT32);
} else if (to.isNumber()) {
- invokeStatic(method, JSType.TO_NUMBER);
+ invokestatic(method, JSType.TO_NUMBER);
} else if (to.isLong()) {
- invokeStatic(method, JSType.TO_INT64);
+ invokestatic(method, JSType.TO_LONG);
} else if (to.isBoolean()) {
- invokeStatic(method, JSType.TO_BOOLEAN);
+ invokestatic(method, JSType.TO_BOOLEAN);
} else if (to.isString()) {
- invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+ invokestatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+ } else if (to.isCharSequence()) {
+ invokestatic(method, JSType.TO_PRIMITIVE_TO_CHARSEQUENCE);
} else {
- assert false : "Illegal conversion " + this + " -> " + to + " " + isString() + " " + toString;
+ throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to + " " + isString() + " " + toString);
}
return to;
@@ -165,4 +185,9 @@ class ObjectType extends Type {
public void _return(final MethodVisitor method) {
method.visitInsn(ARETURN);
}
+
+ @Override
+ public char getBytecodeStackType() {
+ return 'A';
+ }
}
diff --git a/src/jdk/nashorn/internal/codegen/types/Range.java b/src/jdk/nashorn/internal/codegen/types/Range.java
deleted file mode 100644
index 2845d902..00000000
--- a/src/jdk/nashorn/internal/codegen/types/Range.java
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.codegen.types;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.JSType;
-
-/**
- * Represents the value range of a symbol.
- */
-public abstract class Range {
-
- private static final Range GENERIC_RANGE = new Range() {
- @Override
- public Type getType() {
- return Type.OBJECT;
- }
- };
-
- private static final Range NUMBER_RANGE = new Range() {
- @Override
- public Type getType() {
- return Type.NUMBER;
- }
- };
-
- private static final Range UNKNOWN_RANGE = new Range() {
- @Override
- public Type getType() {
- return Type.UNKNOWN;
- }
-
- @Override
- public boolean isUnknown() {
- return true;
- }
- };
-
- private static class IntegerRange extends Range {
- private final long min;
- private final long max;
- private final Type type;
-
- private IntegerRange(final long min, final long max) {
- assert min <= max;
- this.min = min;
- this.max = max;
- this.type = typeFromRange(min, max);
- }
-
- private static Type typeFromRange(final long from, final long to) {
- if (from >= Integer.MIN_VALUE && to <= Integer.MAX_VALUE) {
- return Type.INT;
- }
- return Type.LONG;
- }
-
- @Override
- public Type getType() {
- return type;
- }
-
- public long getMin() {
- return min;
- }
-
- public long getMax() {
- return max;
- }
-
- @Override
- public boolean isIntegerConst() {
- return getMin() == getMax();
- }
-
- private long getBitMask() {
- if (min == max) {
- return min;
- }
-
- if (min < 0) {
- return ~0L;
- }
-
- long mask = 1;
- while (mask < max) {
- mask = (mask << 1) | 1;
- }
- return mask;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (obj instanceof IntegerRange) {
- final IntegerRange other = (IntegerRange)obj;
- return this.type == other.type && this.min == other.min && this.max == other.max;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Long.hashCode(min) ^ Long.hashCode(max);
- }
-
- @Override
- public String toString() {
- return super.toString() + "[" + min +", " + max + "]";
- }
- }
-
- /**
- * Get narrowest type for this range
- * @return type
- */
- public abstract Type getType();
-
- /**
- * Is this range unknown
- * @return true if unknown
- */
- public boolean isUnknown() {
- return false;
- }
-
- /**
- * Check if an integer is enough to span this range
- * @return true if integer is enough
- */
- public boolean isIntegerType() {
- return this instanceof IntegerRange;
- }
-
- /**
- * Check if an integer is enough to span this range
- * @return true if integer is enough
- */
- public boolean isIntegerConst() {
- return false;
- }
-
- /**
- * Create an unknown range - this is most likely a singleton object
- * and it represents "we have no known range information"
- * @return the range
- */
- public static Range createUnknownRange() {
- return UNKNOWN_RANGE;
- }
-
- /**
- * Create a constant range: [value, value]
- * @param value value
- * @return the range
- */
- public static Range createRange(final int value) {
- return createIntegerRange(value, value);
- }
-
- /**
- * Create a constant range: [value, value]
- * @param value value
- * @return the range
- */
- public static Range createRange(final long value) {
- return createIntegerRange(value, value);
- }
-
- /**
- * Create a constant range: [value, value]
- * @param value value
- * @return the range
- */
- public static Range createRange(final double value) {
- if (isRepresentableAsLong(value)) {
- return createIntegerRange((long) value, (long) value);
- }
- return createNumberRange();
- }
-
- /**
- * Create a constant range: [value, value]
- * @param value value
- * @return the range
- */
- public static Range createRange(final Object value) {
- if (value instanceof Integer) {
- return createRange((int)value);
- } else if (value instanceof Long) {
- return createRange((long)value);
- } else if (value instanceof Double) {
- return createRange((double)value);
- }
-
- return createGenericRange();
- }
-
- /**
- * Create a generic range - object symbol that carries no range
- * information
- * @return the range
- */
- public static Range createGenericRange() {
- return GENERIC_RANGE;
- }
-
- /**
- * Create a number range - number symbol that carries no range
- * information
- * @return the range
- */
- public static Range createNumberRange() {
- return NUMBER_RANGE;
- }
-
- /**
- * Create an integer range [min, max]
- * @param min minimum value, inclusive
- * @param max maximum value, inclusive
- * @return the range
- */
- public static IntegerRange createIntegerRange(final long min, final long max) {
- return new IntegerRange(min, max);
- }
-
- /**
- * Create an integer range of maximum type width for the given type
- * @param type the type
- * @return the range
- */
- public static IntegerRange createIntegerRange(final Type type) {
- assert type.isNumeric() && !type.isNumber();
- final long min;
- final long max;
- if (type.isInteger()) {
- min = Integer.MIN_VALUE;
- max = Integer.MAX_VALUE;
- } else if (type.isLong()) {
- min = Long.MIN_VALUE;
- max = Long.MAX_VALUE;
- } else {
- throw new AssertionError(); //type incompatible with integer range
- }
- return new IntegerRange(min, max);
- }
-
- /**
- * Create an range of maximum type width for the given type
- * @param type the type
- * @return the range
- */
- public static Range createTypeRange(final Type type) {
- if (type.isNumber()) {
- return createNumberRange();
- } else if (type.isNumeric()) {
- return createIntegerRange(type);
- } else {
- return createGenericRange();
- }
- }
-
- // check that add doesn't overflow
- private static boolean checkAdd(final long a, final long b) {
- final long result = a + b;
- return ((a ^ result) & (b ^ result)) >= 0;
- }
-
- // check that sub doesn't overflow
- private static boolean checkSub(final long a, final long b) {
- final long result = a - b;
- return ((a ^ result) & (b ^ result)) >= 0;
- }
-
- private static boolean checkMul(final long a, final long b) {
- // TODO correct overflow check
- return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE && b >= Integer.MIN_VALUE && b <= Integer.MAX_VALUE;
- }
-
- /**
- * The range functionality class responsible for merging ranges and drawing
- * range conclusions from operations executed
- */
- public static class Functionality {
- /** logger */
- protected final DebugLogger log;
-
- /**
- * Constructor
- * @param log logger
- */
- public Functionality(final DebugLogger log) {
- this.log = log;
- }
-
- /**
- * Join two ranges
- * @param a first range
- * @param b second range
- * @return the joined range
- */
- public Range join(final Range a, final Range b) {
- if (a.equals(b)) {
- return a;
- }
-
- Type joinedType = a.getType();
- if (a.getType() != b.getType()) {
- if (a.isUnknown()) {
- return b;
- }
- if (b.isUnknown()) {
- return a;
- }
-
- joinedType = Type.widest(a.getType(), b.getType());
- }
-
- if (joinedType.isInteger() || joinedType.isLong()) {
- return createIntegerRange(
- Math.min(((IntegerRange) a).getMin(), ((IntegerRange) b).getMin()),
- Math.max(((IntegerRange) a).getMax(), ((IntegerRange) b).getMax()));
- }
-
- return createTypeRange(joinedType);
- }
-
- /**
- * Add operation
- * @param a range of first symbol to be added
- * @param b range of second symbol to be added
- * @return resulting range representing the value range after add
- */
- public Range add(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final IntegerRange lhs = (IntegerRange)a;
- final IntegerRange rhs = (IntegerRange)b;
- if (checkAdd(lhs.getMin(), rhs.getMin()) && checkAdd(lhs.getMax(), rhs.getMax())) {
- return createIntegerRange(lhs.getMin() + rhs.getMin(), lhs.getMax() + rhs.getMax());
- }
- }
-
- if (a.getType().isNumeric() && b.getType().isNumeric()) {
- return createNumberRange();
- }
-
- return createGenericRange();
- }
-
- /**
- * Sub operation
- * @param a range of first symbol to be subtracted
- * @param b range of second symbol to be subtracted
- * @return resulting range representing the value range after subtraction
- */
- public Range sub(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final IntegerRange lhs = (IntegerRange)a;
- final IntegerRange rhs = (IntegerRange)b;
- if (checkSub(lhs.getMin(), rhs.getMax()) && checkSub(lhs.getMax(), rhs.getMin())) {
- return createIntegerRange(lhs.getMin() - rhs.getMax(), lhs.getMax() - rhs.getMin());
- }
- }
-
- if (a.getType().isNumeric() && b.getType().isNumeric()) {
- return createNumberRange();
- }
-
- return createGenericRange();
- }
-
- /**
- * Mul operation
- * @param a range of first symbol to be multiplied
- * @param b range of second symbol to be multiplied
- * @return resulting range representing the value range after multiplication
- */
- public Range mul(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final IntegerRange lhs = (IntegerRange)a;
- final IntegerRange rhs = (IntegerRange)b;
-
- //ensure that nothing ever overflows or underflows
- if (checkMul(lhs.getMin(), rhs.getMin()) &&
- checkMul(lhs.getMax(), rhs.getMax()) &&
- checkMul(lhs.getMin(), rhs.getMax()) &&
- checkMul(lhs.getMax(), rhs.getMin())) {
-
- final List<Long> results =
- Arrays.asList(
- lhs.getMin() * rhs.getMin(),
- lhs.getMin() * rhs.getMax(),
- lhs.getMax() * rhs.getMin(),
- lhs.getMax() * rhs.getMax());
- return createIntegerRange(Collections.min(results), Collections.max(results));
- }
- }
-
- if (a.getType().isNumeric() && b.getType().isNumeric()) {
- return createNumberRange();
- }
-
- return createGenericRange();
- }
-
- /**
- * Neg operation
- * @param a range of value symbol to be negated
- * @return resulting range representing the value range after neg
- */
- public Range neg(final Range a) {
- if (a.isIntegerType()) {
- final IntegerRange rhs = (IntegerRange)a;
- if (rhs.getMin() != Long.MIN_VALUE && rhs.getMax() != Long.MIN_VALUE) {
- return createIntegerRange(-rhs.getMax(), -rhs.getMin());
- }
- }
-
- if (a.getType().isNumeric()) {
- return createNumberRange();
- }
-
- return createGenericRange();
- }
-
- /**
- * Bitwise and operation
- * @param a range of first symbol to be and:ed
- * @param b range of second symbol to be and:ed
- * @return resulting range representing the value range after and
- */
- public Range and(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final int resultMask = (int) (((IntegerRange)a).getBitMask() & ((IntegerRange)b).getBitMask());
- if (resultMask >= 0) {
- return createIntegerRange(0, resultMask);
- }
- } else if (a.isUnknown() && b.isIntegerType()) {
- final long operandMask = ((IntegerRange)b).getBitMask();
- if (operandMask >= 0) {
- return createIntegerRange(0, operandMask);
- }
- } else if (a.isIntegerType() && b.isUnknown()) {
- final long operandMask = ((IntegerRange)a).getBitMask();
- if (operandMask >= 0) {
- return createIntegerRange(0, operandMask);
- }
- }
-
- return createTypeRange(Type.INT);
- }
-
- /**
- * Bitwise or operation
- * @param a range of first symbol to be or:ed
- * @param b range of second symbol to be or:ed
- * @return resulting range representing the value range after or
- */
- public Range or(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
- if (resultMask >= 0) {
- return createIntegerRange(0, resultMask);
- }
- }
-
- return createTypeRange(Type.INT);
- }
-
- /**
- * Bitwise xor operation
- * @param a range of first symbol to be xor:ed
- * @param b range of second symbol to be xor:ed
- * @return resulting range representing the value range after and
- */
- public Range xor(final Range a, final Range b) {
- if (a.isIntegerConst() && b.isIntegerConst()) {
- return createRange(((IntegerRange)a).getMin() ^ ((IntegerRange)b).getMin());
- }
-
- if (a.isIntegerType() && b.isIntegerType()) {
- final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
- if (resultMask >= 0) {
- return createIntegerRange(0, createIntegerRange(0, resultMask).getBitMask());
- }
- }
- return createTypeRange(Type.INT);
- }
-
- /**
- * Bitwise shl operation
- * @param a range of first symbol to be shl:ed
- * @param b range of second symbol to be shl:ed
- * @return resulting range representing the value range after shl
- */
- public Range shl(final Range a, final Range b) {
- if (b.isIntegerType() && b.isIntegerConst()) {
- final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
- final int shift = (int)((IntegerRange) b).getMin() & 0x1f;
- final int min = (int)left.getMin() << shift;
- final int max = (int)left.getMax() << shift;
- if (min >> shift == left.getMin() && max >> shift == left.getMax()) {
- return createIntegerRange(min, max);
- }
- }
-
- return createTypeRange(Type.INT);
- }
-
- /**
- * Bitwise shr operation
- * @param a range of first symbol to be shr:ed
- * @param b range of second symbol to be shr:ed
- * @return resulting range representing the value range after shr
- */
- public Range shr(final Range a, final Range b) {
- if (b.isIntegerType() && b.isIntegerConst()) {
- final long shift = ((IntegerRange) b).getMin() & 0x1f;
- final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
- if (left.getMin() >= 0) {
- long min = left.getMin() >>> shift;
- long max = left.getMax() >>> shift;
- return createIntegerRange(min, max);
- } else if (shift >= 1) {
- return createIntegerRange(0, JSType.MAX_UINT >>> shift);
- }
- }
-
- return createTypeRange(Type.INT);
- }
-
- /**
- * Bitwise sar operation
- * @param a range of first symbol to be sar:ed
- * @param b range of second symbol to be sar:ed
- * @return resulting range representing the value range after sar
- */
- public Range sar(final Range a, final Range b) {
- if (b.isIntegerType() && b.isIntegerConst()) {
- final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
- final long shift = ((IntegerRange) b).getMin() & 0x1f;
- final long min = left.getMin() >> shift;
- final long max = left.getMax() >> shift;
- return createIntegerRange(min, max);
- }
-
- return createTypeRange(Type.INT);
- }
-
- /**
- * Modulo operation
- * @param a range of first symbol to the mod operation
- * @param b range of second symbol to be mod operation
- * @return resulting range representing the value range after mod
- */
- public Range mod(final Range a, final Range b) {
- if (a.isIntegerType() && b.isIntegerType()) {
- final IntegerRange rhs = (IntegerRange) b;
- if (rhs.getMin() > 0 || rhs.getMax() < 0) { // divisor range must not include 0
- final long absmax = Math.max(Math.abs(rhs.getMin()), Math.abs(rhs.getMax())) - 1;
- return createIntegerRange(rhs.getMin() > 0 ? 0 : -absmax, rhs.getMax() < 0 ? 0 : +absmax);
- }
- }
- return createTypeRange(Type.NUMBER);
- }
-
- /**
- * Division operation
- * @param a range of first symbol to the division
- * @param b range of second symbol to be division
- * @return resulting range representing the value range after division
- */
- public Range div(final Range a, final Range b) {
- // TODO
- return createTypeRange(Type.NUMBER);
- }
- }
-
- /**
- * Simple trace functionality that will log range creation
- */
- public static class TraceFunctionality extends Functionality {
- TraceFunctionality(final DebugLogger log) {
- super(log);
- }
-
- private Range trace(final Range result, final String operation, final Range... operands) {
- log.fine("range::" + operation + Arrays.toString(operands) + " => " + result);
- return result;
- }
-
- @Override
- public Range join(final Range a, final Range b) {
- final Range result = super.join(a, b);
- if (!a.equals(b)) {
- trace(result, "join", a, b);
- }
- return result;
- }
-
- @Override
- public Range add(final Range a, final Range b) {
- return trace(super.add(a, b), "add", a, b);
- }
-
- @Override
- public Range sub(final Range a, final Range b) {
- return trace(super.sub(a, b), "sub", a, b);
- }
-
- @Override
- public Range mul(final Range a, final Range b) {
- return trace(super.mul(a, b), "mul", a, b);
- }
-
- @Override
- public Range neg(final Range a) {
- return trace(super.neg(a), "neg", a);
- }
-
- @Override
- public Range and(final Range a, final Range b) {
- return trace(super.and(a, b), "and", a, b);
- }
-
- @Override
- public Range or(final Range a, final Range b) {
- return trace(super.or(a, b), "or", a, b);
- }
-
- @Override
- public Range xor(final Range a, final Range b) {
- return trace(super.xor(a, b), "xor", a, b);
- }
-
- @Override
- public Range shl(final Range a, final Range b) {
- return trace(super.shl(a, b), "shl", a, b);
- }
-
- @Override
- public Range shr(final Range a, final Range b) {
- return trace(super.shr(a, b), "shr", a, b);
- }
-
- @Override
- public Range sar(final Range a, final Range b) {
- return trace(super.sar(a, b), "sar", a, b);
- }
-
- @Override
- public Range mod(final Range a, final Range b) {
- return trace(super.mod(a, b), "mod", a, b);
- }
-
- @Override
- public Range div(final Range a, final Range b) {
- return trace(super.div(a, b), "div", a, b);
- }
- }
-
- @Override
- public String toString() {
- return String.valueOf(getType());
- }
-
- @SuppressWarnings("unused")
- private static boolean isRepresentableAsInt(final double number) {
- return (int)number == number && !isNegativeZero(number);
- }
-
- private static boolean isRepresentableAsLong(final double number) {
- return (long)number == number && !isNegativeZero(number);
- }
-
- private static boolean isNegativeZero(final double number) {
- return Double.doubleToLongBits(number) == Double.doubleToLongBits(-0.0);
- }
-}
diff --git a/src/jdk/nashorn/internal/codegen/types/Type.java b/src/jdk/nashorn/internal/codegen/types/Type.java
index 4799c264..2cf2d9b8 100644
--- a/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -33,6 +33,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.DUP2_X1;
import static jdk.internal.org.objectweb.asm.Opcodes.DUP2_X2;
import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X1;
import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X2;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE;
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
@@ -45,13 +46,28 @@ import static jdk.internal.org.objectweb.asm.Opcodes.SWAP;
import static jdk.internal.org.objectweb.asm.Opcodes.T_DOUBLE;
import static jdk.internal.org.objectweb.asm.Opcodes.T_INT;
import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
* This is the representation of a JavaScript type, disassociated from java
@@ -74,29 +90,44 @@ import jdk.nashorn.internal.codegen.CompilerConstants.Call;
* INTs rather than OBJECTs
*/
-public abstract class Type implements Comparable<Type>, BytecodeOps {
+public abstract class Type implements Comparable<Type>, BytecodeOps, Serializable {
+ private static final long serialVersionUID = 1L;
/** Human readable name for type */
- private final String name;
+ private transient final String name;
/** Descriptor for type */
- private final String descriptor;
+ private transient final String descriptor;
/** The "weight" of the type. Used for picking widest/least specific common type */
- private final int weight;
+ private transient final int weight;
/** How many bytecode slots does this type occupy */
- private final int slots;
+ private transient final int slots;
/** The class for this type */
private final Class<?> clazz;
+ /**
+ * Cache for internal types - this is a query that requires complex stringbuilding inside
+ * ASM and it saves startup time to cache the type mappings
+ */
+ private static final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> INTERNAL_TYPE_CACHE =
+ Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>());
+
+ /** Internal ASM type for this Type - computed once at construction */
+ private transient final jdk.internal.org.objectweb.asm.Type internalType;
+
/** Weights are used to decide which types are "wider" than other types */
protected static final int MIN_WEIGHT = -1;
/** Set way below Integer.MAX_VALUE to prevent overflow when adding weights. Objects are still heaviest. */
protected static final int MAX_WEIGHT = 20;
+ static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "mathBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class);
+
+ static final Handle MATHBOOTSTRAP = new Handle(H_INVOKESTATIC, BOOTSTRAP.className(), "mathBootstrap", BOOTSTRAP.descriptor());
+
/**
* Constructor
*
@@ -105,12 +136,13 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
* @param slots how many bytecode slots the type takes up
*/
Type(final String name, final Class<?> clazz, final int weight, final int slots) {
- this.name = name;
- this.clazz = clazz;
- this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
- this.weight = weight;
+ this.name = name;
+ this.clazz = clazz;
+ this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
+ this.weight = weight;
assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight;
- this.slots = slots;
+ this.slots = slots;
+ this.internalType = getInternalType(clazz);
}
/**
@@ -149,6 +181,17 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
/**
+ * Returns the character describing the bytecode type for this value on the stack or local variable, identical to
+ * what would be used as the prefix for a bytecode {@code LOAD} or {@code STORE} instruction, therefore it must be
+ * one of {@code A, F, D, I, L}. Also, the special value {@code U} is used for local variable slots that haven't
+ * been initialized yet (it can't appear for a value pushed to the operand stack, those always have known values).
+ * Note that while we allow all JVM internal types, Nashorn doesn't necessarily use them all - currently we don't
+ * have floats, only doubles, but that might change in the future.
+ * @return the character describing the bytecode type for this value on the stack.
+ */
+ public abstract char getBytecodeStackType();
+
+ /**
* Generate a method descriptor given a return type and a param array
*
* @param returnType return type
@@ -181,6 +224,20 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
/**
+ * Return a character representing {@code type} in a method signature.
+ *
+ * @param type parameter type
+ * @return descriptor character
+ */
+ public static char getShortSignatureDescriptor(final Type type) {
+ // Use 'Z' for boolean parameters as we need to distinguish from int
+ if (type instanceof BooleanType) {
+ return 'Z';
+ }
+ return type.getBytecodeStackType();
+ }
+
+ /**
* Return the type for an internal type, package private - do not use
* outside code gen
*
@@ -199,7 +256,11 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
case jdk.internal.org.objectweb.asm.Type.DOUBLE:
return NUMBER;
case jdk.internal.org.objectweb.asm.Type.OBJECT:
- return OBJECT;
+ try {
+ return Type.typeFor(Class.forName(itype.getClassName()));
+ } catch(final ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
case jdk.internal.org.objectweb.asm.Type.VOID:
return null;
case jdk.internal.org.objectweb.asm.Type.ARRAY:
@@ -248,19 +309,88 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
return types;
}
+ /**
+ * Write a map of {@code int} to {@code Type} to an output stream. This is used to store deoptimization state.
+ *
+ * @param typeMap the type map
+ * @param output data output
+ * @throws IOException if write cannot be completed
+ */
+ public static void writeTypeMap(final Map<Integer, Type> typeMap, final DataOutput output) throws IOException {
+ if (typeMap == null) {
+ output.writeInt(0);
+ } else {
+ output.writeInt(typeMap.size());
+ for(final Map.Entry<Integer, Type> e: typeMap.entrySet()) {
+ output.writeInt(e.getKey());
+ final byte typeChar;
+ final Type type = e.getValue();
+ if(type == Type.OBJECT) {
+ typeChar = 'L';
+ } else if (type == Type.NUMBER) {
+ typeChar = 'D';
+ } else if (type == Type.LONG) {
+ typeChar = 'J';
+ } else {
+ throw new AssertionError();
+ }
+ output.writeByte(typeChar);
+ }
+ }
+ }
+
+ /**
+ * Read a map of {@code int} to {@code Type} from an input stream. This is used to store deoptimization state.
+ *
+ * @param input data input
+ * @return type map
+ * @throws IOException if read cannot be completed
+ */
+ public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException {
+ final int size = input.readInt();
+ if (size <= 0) {
+ return null;
+ }
+ final Map<Integer, Type> map = new TreeMap<>();
+ for(int i = 0; i < size; ++i) {
+ final int pp = input.readInt();
+ final int typeChar = input.readByte();
+ final Type type;
+ switch (typeChar) {
+ case 'L': type = Type.OBJECT; break;
+ case 'D': type = Type.NUMBER; break;
+ case 'J': type = Type.LONG; break;
+ default: continue;
+ }
+ map.put(pp, type);
+ }
+ return map;
+ }
+
static jdk.internal.org.objectweb.asm.Type getInternalType(final String className) {
return jdk.internal.org.objectweb.asm.Type.getType(className);
}
private jdk.internal.org.objectweb.asm.Type getInternalType() {
- return jdk.internal.org.objectweb.asm.Type.getType(getTypeClass());
+ return internalType;
+ }
+
+ private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) {
+ final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> c = INTERNAL_TYPE_CACHE;
+ jdk.internal.org.objectweb.asm.Type itype = c.get(type);
+ if (itype != null) {
+ return itype;
+ }
+ itype = jdk.internal.org.objectweb.asm.Type.getType(type);
+ c.put(type, itype);
+ return itype;
}
private static jdk.internal.org.objectweb.asm.Type getInternalType(final Class<?> type) {
- return jdk.internal.org.objectweb.asm.Type.getType(type);
+ return lookupInternalType(type);
}
- static void invokeStatic(final MethodVisitor method, final Call call) {
+ static void invokestatic(final MethodVisitor method, final Call call) {
method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor(), false);
}
@@ -373,6 +503,14 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
/**
+ * Is this a primitive type (e.g int, long, double, boolean)
+ * @return true if primitive
+ */
+ public boolean isPrimitive() {
+ return !isObject();
+ }
+
+ /**
* Determines whether a type is a STRING type
*
* @return true if object type, false otherwise
@@ -382,6 +520,15 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
/**
+ * Determines whether a type is a CHARSEQUENCE type used internally strings
+ *
+ * @return true if CharSequence (internal string) type, false otherwise
+ */
+ public boolean isCharSequence() {
+ return this.equals(Type.CHARSEQUENCE);
+ }
+
+ /**
* Determine if two types are equivalent, i.e. need no conversion
*
* @param type the second type to check
@@ -389,7 +536,7 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
* @return true if types are equivalent, false otherwise
*/
public boolean isEquivalentTo(final Type type) {
- return this.weight() == type.weight() || (isObject() && type.isObject());
+ return this.weight() == type.weight() || isObject() && type.isObject();
}
/**
@@ -439,6 +586,7 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
public int getSlots() {
return slots;
}
+
/**
* Returns the widest or most common of two types
*
@@ -462,6 +610,49 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
/**
+ * Returns the widest or most common of two types, given as classes
+ *
+ * @param type0 type one
+ * @param type1 type two
+ *
+ * @return the widest type
+ */
+ public static Class<?> widest(final Class<?> type0, final Class<?> type1) {
+ return widest(Type.typeFor(type0), Type.typeFor(type1)).getTypeClass();
+ }
+
+ /**
+ * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to
+ * anything other than object. Note that this wouldn't be necessary if {@code Type.widest} did not allow
+ * boolean-to-number widening. Eventually, we should address it there, but it affects too many other parts of the
+ * system and is sometimes legitimate (e.g. whenever a boolean value would undergo ToNumber conversion anyway).
+ * @param t1 type 1
+ * @param t2 type 2
+ * @return wider of t1 and t2, except if one is boolean and the other is neither boolean nor unknown, in which case
+ * {@code Type.OBJECT} is returned.
+ */
+ public static Type widestReturnType(final Type t1, final Type t2) {
+ if (t1.isUnknown()) {
+ return t2;
+ } else if (t2.isUnknown()) {
+ return t1;
+ } else if(t1.isBoolean() != t2.isBoolean() || t1.isNumeric() != t2.isNumeric()) {
+ return Type.OBJECT;
+ }
+ return Type.widest(t1, t2);
+ }
+
+ /**
+ * Returns a generic version of the type. Basically, if the type {@link #isObject()}, returns {@link #OBJECT},
+ * otherwise returns the type unchanged.
+ * @param type the type to generify
+ * @return the generified type
+ */
+ public static Type generic(final Type type) {
+ return type.isObject() ? Type.OBJECT : type;
+ }
+
+ /**
* Returns the narrowest or least common of two types
*
* @param type0 type one
@@ -470,7 +661,25 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
* @return the widest type
*/
public static Type narrowest(final Type type0, final Type type1) {
- return type0.weight() < type1.weight() ? type0 : type1;
+ return type0.narrowerThan(type1) ? type0 : type1;
+ }
+
+ /**
+ * Check whether this type is strictly narrower than another one
+ * @param type type to check against
+ * @return true if this type is strictly narrower
+ */
+ public boolean narrowerThan(final Type type) {
+ return weight() < type.weight();
+ }
+
+ /**
+ * Check whether this type is strictly wider than another one
+ * @param type type to check against
+ * @return true if this type is strictly wider
+ */
+ public boolean widerThan(final Type type) {
+ return weight() > type.weight();
}
/**
@@ -549,6 +758,16 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
return descriptor;
}
+ /**
+ * Return the descriptor of a type, short version
+ * Used mainly for debugging purposes
+ *
+ * @return the short descriptor
+ */
+ public String getShortDescriptor() {
+ return descriptor;
+ }
+
@Override
public String toString() {
return name;
@@ -688,17 +907,17 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
/**
* This is an integer type, i.e INT, INT32.
*/
- public static final Type INT = putInCache(new IntType());
+ public static final BitwiseType INT = putInCache(new IntType());
/**
* This is the number singleton, used for all number types
*/
- public static final Type NUMBER = putInCache(new NumberType());
+ public static final NumericType NUMBER = putInCache(new NumberType());
/**
* This is the long singleton, used for all long types
*/
- public static final Type LONG = putInCache(new LongType());
+ public static final BitwiseType LONG = putInCache(new LongType());
/**
* A string singleton
@@ -706,14 +925,33 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
public static final Type STRING = putInCache(new ObjectType(String.class));
/**
+ * This is the CharSequence singleton used to represent JS strings internally
+ * (either a {@code java.lang.String} or {@code jdk.nashorn.internal.runtime.ConsString}.
+ */
+ public static final Type CHARSEQUENCE = putInCache(new ObjectType(CharSequence.class));
+
+
+ /**
* This is the object singleton, used for all object types
*/
public static final Type OBJECT = putInCache(new ObjectType());
/**
+ * A undefined singleton
+ */
+ public static final Type UNDEFINED = putInCache(new ObjectType(Undefined.class));
+
+ /**
+ * This is the singleton for ScriptObjects
+ */
+ public static final Type SCRIPT_OBJECT = putInCache(new ObjectType(ScriptObject.class));
+
+ /**
* This is the singleton for integer arrays
*/
public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
+ private static final long serialVersionUID = 1L;
+
@Override
public void astore(final MethodVisitor method) {
method.visitInsn(IASTORE);
@@ -741,6 +979,8 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
* This is the singleton for long arrays
*/
public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
+ private static final long serialVersionUID = 1L;
+
@Override
public void astore(final MethodVisitor method) {
method.visitInsn(LASTORE);
@@ -768,6 +1008,8 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
* This is the singleton for numeric arrays
*/
public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
+ private static final long serialVersionUID = 1L;
+
@Override
public void astore(final MethodVisitor method) {
method.visitInsn(DASTORE);
@@ -802,6 +1044,8 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
/** This type, always an object type, just a toString override */
public static final Type THIS = new ObjectType() {
+ private static final long serialVersionUID = 1L;
+
@Override
public String toString() {
return "this";
@@ -810,6 +1054,8 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
/** Scope type, always an object type, just a toString override */
public static final Type SCOPE = new ObjectType() {
+ private static final long serialVersionUID = 1L;
+
@Override
public String toString() {
return "scope";
@@ -820,60 +1066,100 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
// EMPTY - used as a class that is absolutely not compatible with a type to represent "unknown"
}
- /**
- * This is the unknown type which is used as initial type for type
- * inference. It has the minimum type width
- */
- public static final Type UNKNOWN = new Type("<unknown>", Unknown.class, MIN_WEIGHT, 1) {
+ private abstract static class ValueLessType extends Type {
+ private static final long serialVersionUID = 1L;
- @Override
- public String getDescriptor() {
- return "<unknown>";
+ ValueLessType(final String name) {
+ super(name, Unknown.class, MIN_WEIGHT, 1);
}
@Override
public Type load(final MethodVisitor method, final int slot) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("load " + slot);
}
@Override
public void store(final MethodVisitor method, final int slot) {
- assert false : "unsupported operation";
+ throw new UnsupportedOperationException("store " + slot);
}
@Override
public Type ldc(final MethodVisitor method, final Object c) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("ldc " + c);
}
@Override
public Type loadUndefined(final MethodVisitor method) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("load undefined");
+ }
+
+ @Override
+ public Type loadForcedInitializer(final MethodVisitor method) {
+ throw new UnsupportedOperationException("load forced initializer");
}
@Override
public Type convert(final MethodVisitor method, final Type to) {
- assert false : "unsupported operation";
- return null;
+ throw new UnsupportedOperationException("convert => " + to);
}
@Override
public void _return(final MethodVisitor method) {
- assert false : "unsupported operation";
+ throw new UnsupportedOperationException("return");
+ }
+
+ @Override
+ public Type add(final MethodVisitor method, final int programPoint) {
+ throw new UnsupportedOperationException("add");
+ }
+ }
+
+ /**
+ * This is the unknown type which is used as initial type for type
+ * inference. It has the minimum type width
+ */
+ public static final Type UNKNOWN = new ValueLessType("<unknown>") {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getDescriptor() {
+ return "<unknown>";
}
@Override
- public Type add(final MethodVisitor method) {
- assert false : "unsupported operation";
- return null;
+ public char getBytecodeStackType() {
+ return 'U';
}
};
- private static <T extends Type> T putInCache(T type) {
+ /**
+ * This is the unknown type which is used as initial type for type
+ * inference. It has the minimum type width
+ */
+ public static final Type SLOT_2 = new ValueLessType("<slot_2>") {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getDescriptor() {
+ return "<slot_2>";
+ }
+
+ @Override
+ public char getBytecodeStackType() {
+ throw new UnsupportedOperationException("getBytecodeStackType");
+ }
+ };
+
+ private static <T extends Type> T putInCache(final T type) {
cache.put(type.getTypeClass(), type);
return type;
}
+
+ /**
+ * Read resolve
+ * @return resolved type
+ */
+ protected final Object readResolve() {
+ return Type.typeFor(clazz);
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/AccessNode.java b/src/jdk/nashorn/internal/ir/AccessNode.java
index 957adf69..b8b64820 100644
--- a/src/jdk/nashorn/internal/ir/AccessNode.java
+++ b/src/jdk/nashorn/internal/ir/AccessNode.java
@@ -25,16 +25,21 @@
package jdk.nashorn.internal.ir;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
/**
* IR representation of a property access (period operator.)
*/
@Immutable
public final class AccessNode extends BaseNode {
- /** Property ident. */
- private final IdentNode property;
+ private static final long serialVersionUID = 1L;
+
+ /** Property name. */
+ private final String property;
/**
* Constructor
@@ -44,13 +49,13 @@ public final class AccessNode extends BaseNode {
* @param base base node
* @param property property
*/
- public AccessNode(final long token, final int finish, final Expression base, final IdentNode property) {
+ public AccessNode(final long token, final int finish, final Expression base, final String property) {
super(token, finish, base, false);
- this.property = property.setIsPropertyName();
+ this.property = property;
}
- private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction) {
- super(accessNode, base, isFunction);
+ private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) {
+ super(accessNode, base, isFunction, type, id);
this.property = property;
}
@@ -62,59 +67,78 @@ public final class AccessNode extends BaseNode {
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterAccessNode(this)) {
return visitor.leaveAccessNode(
- setBase((Expression)base.accept(visitor)).
- setProperty((IdentNode)property.accept(visitor)));
+ setBase((Expression)base.accept(visitor)));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
final boolean needsParen = tokenType().needsParens(getBase().tokenType(), true);
+ if (printType) {
+ optimisticTypeToString(sb);
+ }
+
if (needsParen) {
sb.append('(');
}
- base.toString(sb);
+ base.toString(sb, printType);
if (needsParen) {
sb.append(')');
}
sb.append('.');
- sb.append(property.getName());
+ sb.append(property);
}
/**
- * Get the property
+ * Get the property name
*
- * @return the property IdentNode
+ * @return the property name
*/
- public IdentNode getProperty() {
+ public String getProperty() {
return property;
}
+ /**
+ * Return true if this node represents an index operation normally represented as {@link IndexNode}.
+ * @return true if an index access.
+ */
+ public boolean isIndex() {
+ return Token.descType(getToken()) == TokenType.LBRACKET;
+ }
+
private AccessNode setBase(final Expression base) {
if (this.base == base) {
return this;
}
- return new AccessNode(this, base, property, isFunction());
+ return new AccessNode(this, base, property, isFunction(), type, programPoint);
}
- private AccessNode setProperty(final IdentNode property) {
- if (this.property == property) {
+ @Override
+ public AccessNode setType(final Type type) {
+ if (this.type == type) {
return this;
}
- return new AccessNode(this, base, property, isFunction());
+ return new AccessNode(this, base, property, isFunction(), type, programPoint);
}
@Override
- public BaseNode setIsFunction() {
- if (isFunction()) {
+ public AccessNode setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
return this;
}
- return new AccessNode(this, base, property, true);
+ return new AccessNode(this, base, property, isFunction(), type, programPoint);
}
+ @Override
+ public AccessNode setIsFunction() {
+ if (isFunction()) {
+ return this;
+ }
+ return new AccessNode(this, base, property, true, type, programPoint);
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/BaseNode.java b/src/jdk/nashorn/internal/ir/BaseNode.java
index 96f155d1..35479a7a 100644
--- a/src/jdk/nashorn/internal/ir/BaseNode.java
+++ b/src/jdk/nashorn/internal/ir/BaseNode.java
@@ -25,6 +25,10 @@
package jdk.nashorn.internal.ir;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
/**
@@ -34,13 +38,20 @@ import jdk.nashorn.internal.ir.annotations.Immutable;
* @see IndexNode
*/
@Immutable
-public abstract class BaseNode extends Expression implements FunctionCall {
+public abstract class BaseNode extends Expression implements FunctionCall, Optimistic {
+ private static final long serialVersionUID = 1L;
/** Base Node. */
protected final Expression base;
private final boolean isFunction;
+ /** Callsite type for this node, if overridden optimistically or conservatively depending on coercion */
+ protected final Type type;
+
+ /** Program point id */
+ protected final int programPoint;
+
/**
* Constructor
*
@@ -51,8 +62,10 @@ public abstract class BaseNode extends Expression implements FunctionCall {
*/
public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
super(token, base.getStart(), finish);
- this.base = base;
- this.isFunction = isFunction;
+ this.base = base;
+ this.isFunction = isFunction;
+ this.type = null;
+ this.programPoint = INVALID_PROGRAM_POINT;
}
/**
@@ -60,11 +73,15 @@ public abstract class BaseNode extends Expression implements FunctionCall {
* @param baseNode node to inherit from
* @param base base
* @param isFunction is this a function
+ * @param callSiteType the callsite type for this base node, either optimistic or conservative
+ * @param programPoint program point id
*/
- protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction) {
+ protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) {
super(baseNode);
- this.base = base;
- this.isFunction = isFunction;
+ this.base = base;
+ this.isFunction = isFunction;
+ this.type = callSiteType;
+ this.programPoint = programPoint;
}
/**
@@ -80,6 +97,31 @@ public abstract class BaseNode extends Expression implements FunctionCall {
return isFunction;
}
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return type == null ? getMostPessimisticType() : type;
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ return Type.INT;
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return true;
+ }
+
/**
* Mark this node as being the callee operand of a {@link CallNode}.
* @return a base node identical to this one in all aspects except with its function flag set.
diff --git a/src/jdk/nashorn/internal/ir/BinaryNode.java b/src/jdk/nashorn/internal/ir/BinaryNode.java
index 0a1d1bfc..f625fe1a 100644
--- a/src/jdk/nashorn/internal/ir/BinaryNode.java
+++ b/src/jdk/nashorn/internal/ir/BinaryNode.java
@@ -25,7 +25,15 @@
package jdk.nashorn.internal.ir;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.TokenType;
@@ -34,12 +42,40 @@ import jdk.nashorn.internal.parser.TokenType;
* BinaryNode nodes represent two operand operations.
*/
@Immutable
-public final class BinaryNode extends Expression implements Assignment<Expression> {
+public final class BinaryNode extends Expression implements Assignment<Expression>, Optimistic {
+ private static final long serialVersionUID = 1L;
+
+ // Placeholder for "undecided optimistic ADD type". Unfortunately, we can't decide the type of ADD during optimistic
+ // type calculation as it can have local variables as its operands that will decide its ultimate type.
+ private static final Type OPTIMISTIC_UNDECIDED_TYPE = Type.typeFor(new Object(){/*empty*/}.getClass());
+
/** Left hand side argument. */
private final Expression lhs;
private final Expression rhs;
+ private final int programPoint;
+
+ private final Type type;
+
+ private transient Type cachedType;
+ private transient Object cachedTypeFunction;
+
+ @Ignore
+ private static final Set<TokenType> CAN_OVERFLOW =
+ Collections.unmodifiableSet(new HashSet<>(Arrays.asList(new TokenType[] {
+ TokenType.ADD,
+ TokenType.DIV,
+ TokenType.MOD,
+ TokenType.MUL,
+ TokenType.SUB,
+ TokenType.ASSIGN_ADD,
+ TokenType.ASSIGN_DIV,
+ TokenType.ASSIGN_MOD,
+ TokenType.ASSIGN_MUL,
+ TokenType.ASSIGN_SUB
+ })));
+
/**
* Constructor
*
@@ -49,17 +85,25 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
*/
public BinaryNode(final long token, final Expression lhs, final Expression rhs) {
super(token, lhs.getStart(), rhs.getFinish());
+ assert !(isTokenType(TokenType.AND) || isTokenType(TokenType.OR)) || lhs instanceof JoinPredecessorExpression;
this.lhs = lhs;
this.rhs = rhs;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.type = null;
}
- private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs) {
+ private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs, final Type type, final int programPoint) {
super(binaryNode);
this.lhs = lhs;
this.rhs = rhs;
+ this.programPoint = programPoint;
+ this.type = type;
}
- @Override
+ /**
+ * Returns true if the node is a comparison operation.
+ * @return true if the node is a comparison operation.
+ */
public boolean isComparison() {
switch (tokenType()) {
case EQ:
@@ -77,6 +121,36 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
}
/**
+ * Returns true if the node is a logical operation.
+ * @return true if the node is a logical operation.
+ */
+ public boolean isLogical() {
+ return isLogical(tokenType());
+ }
+
+ /**
+ * Returns true if the token type represents a logical operation.
+ * @param tokenType the token type
+ * @return true if the token type represents a logical operation.
+ */
+ public static boolean isLogical(final TokenType tokenType) {
+ switch (tokenType) {
+ case AND:
+ case OR:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+ @Override
+ public Type apply(final Symbol t) {
+ return null;
+ }
+ };
+
+ /**
* Return the widest possible type for this operation. This is used for compile time
* static type inference
*
@@ -84,7 +158,60 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
*/
@Override
public Type getWidestOperationType() {
+ return getWidestOperationType(UNKNOWN_LOCALS);
+ }
+
+ /**
+ * Return the widest possible operand type for this operation.
+ *
+ * @return Type
+ */
+ public Type getWidestOperandType() {
+ switch (tokenType()) {
+ case SHR:
+ case ASSIGN_SHR:
+ return Type.INT;
+ case INSTANCEOF:
+ return Type.OBJECT;
+ default:
+ if (isComparison()) {
+ return Type.OBJECT;
+ }
+ return getWidestOperationType();
+ }
+ }
+
+ private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
switch (tokenType()) {
+ case ADD:
+ case ASSIGN_ADD: {
+ // Compare this logic to decideType(Type, Type); it's similar, but it handles the optimistic type
+ // calculation case while this handles the conservative case.
+ final Type lhsType = lhs.getType(localVariableTypes);
+ final Type rhsType = rhs.getType(localVariableTypes);
+ if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
+ // Will always fit in an int, as the value range is [0, 1, 2]. If we didn't treat them specially here,
+ // they'd end up being treated as generic INT operands and their sum would be conservatively considered
+ // to be a LONG in the generic case below; we can do better here.
+ return Type.INT;
+ } else if(isString(lhsType) || isString(rhsType)) {
+ // We can statically figure out that this is a string if either operand is a string. In this case, use
+ // CHARSEQUENCE to prevent it from being proactively flattened.
+ return Type.CHARSEQUENCE;
+ }
+ final Type widestOperandType = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
+ if(widestOperandType == Type.INT) {
+ return Type.LONG;
+ } else if (widestOperandType.isNumeric()) {
+ return Type.NUMBER;
+ }
+ // We pretty much can't know what it will be statically. Must presume OBJECT conservatively, as we can end
+ // up getting either a string or an object when adding something + object, e.g.:
+ // 1 + {} == "1[object Object]", but
+ // 1 + {valueOf: function() { return 2 }} == 3. Also:
+ // 1 + {valueOf: function() { return "2" }} == "12".
+ return Type.OBJECT;
+ }
case SHR:
case ASSIGN_SHR:
return Type.LONG;
@@ -101,20 +228,68 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
return Type.INT;
case DIV:
case MOD:
+ case ASSIGN_DIV:
+ case ASSIGN_MOD: {
+ // Naively, one might think MOD has the same type as the widest of its operands, this is unfortunately not
+ // true when denominator is zero, so even type(int % int) == double.
+ return Type.NUMBER;
+ }
case MUL:
case SUB:
- case ASSIGN_DIV:
- case ASSIGN_MOD:
case ASSIGN_MUL:
- case ASSIGN_SUB:
+ case ASSIGN_SUB: {
+ final Type lhsType = lhs.getType(localVariableTypes);
+ final Type rhsType = rhs.getType(localVariableTypes);
+ if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
+ return Type.INT;
+ }
+ final Type widestOperandType = Type.widest(booleanToInt(lhsType), booleanToInt(rhsType));
+ if(widestOperandType == Type.INT) {
+ return Type.LONG;
+ }
return Type.NUMBER;
+ }
+ case VOID: {
+ return Type.UNDEFINED;
+ }
+ case ASSIGN: {
+ return rhs.getType(localVariableTypes);
+ }
+ case INSTANCEOF: {
+ return Type.BOOLEAN;
+ }
+ case COMMALEFT: {
+ return lhs.getType(localVariableTypes);
+ }
+ case COMMARIGHT: {
+ return rhs.getType(localVariableTypes);
+ }
+ case AND:
+ case OR:{
+ return Type.widestReturnType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+ }
default:
+ if (isComparison()) {
+ return Type.BOOLEAN;
+ }
return Type.OBJECT;
}
}
+ private static boolean isString(final Type type) {
+ return type == Type.STRING || type == Type.CHARSEQUENCE;
+ }
+
+ private static Type booleanToInt(final Type type) {
+ return type == Type.BOOLEAN ? Type.INT : type;
+ }
+
+ private static Type undefinedToNumber(final Type type) {
+ return type == Type.UNDEFINED ? Type.NUMBER : type;
+ }
+
/**
- * Check if this node is an assigment
+ * Check if this node is an assignment
*
* @return true if this node assigns a value
*/
@@ -150,7 +325,7 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
}
@Override
- public BinaryNode setAssignmentDest(Expression n) {
+ public BinaryNode setAssignmentDest(final Expression n) {
return setLHS(n);
}
@@ -209,17 +384,41 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
}
@Override
- public void toString(final StringBuilder sb) {
- final TokenType type = tokenType();
+ public boolean isAlwaysFalse() {
+ switch (tokenType()) {
+ case COMMALEFT:
+ return lhs.isAlwaysFalse();
+ case COMMARIGHT:
+ return rhs.isAlwaysFalse();
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isAlwaysTrue() {
+ switch (tokenType()) {
+ case COMMALEFT:
+ return lhs.isAlwaysTrue();
+ case COMMARIGHT:
+ return rhs.isAlwaysTrue();
+ default:
+ return false;
+ }
+ }
- final boolean lhsParen = type.needsParens(lhs().tokenType(), true);
- final boolean rhsParen = type.needsParens(rhs().tokenType(), false);
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ final TokenType tokenType = tokenType();
+
+ final boolean lhsParen = tokenType.needsParens(lhs().tokenType(), true);
+ final boolean rhsParen = tokenType.needsParens(rhs().tokenType(), false);
if (lhsParen) {
sb.append('(');
}
- lhs().toString(sb);
+ lhs().toString(sb, printType);
if (lhsParen) {
sb.append(')');
@@ -227,7 +426,7 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
sb.append(' ');
- switch (type) {
+ switch (tokenType) {
case COMMALEFT:
sb.append(",<");
break;
@@ -239,16 +438,20 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
sb.append("++");
break;
default:
- sb.append(type.getName());
+ sb.append(tokenType.getName());
break;
}
+ if (isOptimistic()) {
+ sb.append(Expression.OPT_IDENTIFIER);
+ }
+
sb.append(' ');
if (rhsParen) {
sb.append('(');
}
- rhs().toString(sb);
+ rhs().toString(sb, printType);
if (rhsParen) {
sb.append(')');
}
@@ -279,7 +482,7 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
if (this.lhs == lhs) {
return this;
}
- return new BinaryNode(this, lhs, rhs);
+ return new BinaryNode(this, lhs, rhs, type, programPoint);
}
/**
@@ -291,7 +494,104 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
if (this.rhs == rhs) {
return this;
}
- return new BinaryNode(this, lhs, rhs);
+ return new BinaryNode(this, lhs, rhs, type, programPoint);
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
}
+ @Override
+ public boolean canBeOptimistic() {
+ return isTokenType(TokenType.ADD) || (getMostOptimisticType() != getMostPessimisticType());
+ }
+
+ @Override
+ public BinaryNode setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new BinaryNode(this, lhs, rhs, type, programPoint);
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ final TokenType tokenType = tokenType();
+ if(tokenType == TokenType.ADD || tokenType == TokenType.ASSIGN_ADD) {
+ return OPTIMISTIC_UNDECIDED_TYPE;
+ } else if (CAN_OVERFLOW.contains(tokenType())) {
+ return Type.INT;
+ }
+ return getMostPessimisticType();
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return getWidestOperationType();
+ }
+
+ /**
+ * Returns true if the node has the optimistic type of the node is not yet decided. Optimistic ADD nodes start out
+ * as undecided until we can figure out if they're numeric or not.
+ * @return true if the node has the optimistic type of the node is not yet decided.
+ */
+ public boolean isOptimisticUndecidedType() {
+ return type == OPTIMISTIC_UNDECIDED_TYPE;
+ }
+
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ if(localVariableTypes == cachedTypeFunction) {
+ return cachedType;
+ }
+ cachedType = getTypeUncached(localVariableTypes);
+ cachedTypeFunction = localVariableTypes;
+ return cachedType;
+ }
+
+ private Type getTypeUncached(final Function<Symbol, Type> localVariableTypes) {
+ if(type == OPTIMISTIC_UNDECIDED_TYPE) {
+ return decideType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+ }
+ final Type widest = getWidestOperationType(localVariableTypes);
+ if(type == null) {
+ return widest;
+ }
+ return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes))));
+ }
+
+ private static Type decideType(final Type lhsType, final Type rhsType) {
+ // Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these
+ // are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become
+ // int addition in the general case anyway), and that we also don't conservatively widen sums of ints to
+ // longs, or sums of longs to doubles.
+ if(isString(lhsType) || isString(rhsType)) {
+ return Type.CHARSEQUENCE;
+ }
+ // NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we
+ // bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can
+ // end up returning either a number or a string, and their common supertype is Object, for better or worse.
+ final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
+ return widest.isObject() ? Type.OBJECT : widest;
+ }
+
+ /**
+ * If the node is a node representing an add operation and has {@link #isOptimisticUndecidedType() optimistic
+ * undecided type}, decides its type. Should be invoked after its operands types have been finalized.
+ * @return returns a new node similar to this node, but with its type set to the type decided from the type of its
+ * operands.
+ */
+ public BinaryNode decideType() {
+ assert type == OPTIMISTIC_UNDECIDED_TYPE;
+ return setType(decideType(lhs.getType(), rhs.getType()));
+ }
+
+ @Override
+ public BinaryNode setType(final Type type) {
+ if (this.type == type) {
+ return this;
+ }
+ return new BinaryNode(this, lhs, rhs, type, programPoint);
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/Block.java b/src/jdk/nashorn/internal/ir/Block.java
index f262d8d1..12e4fcd8 100644
--- a/src/jdk/nashorn/internal/ir/Block.java
+++ b/src/jdk/nashorn/internal/ir/Block.java
@@ -33,19 +33,17 @@ import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-
import jdk.nashorn.internal.codegen.Label;
-import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-
/**
* IR representation for a list of statements.
*/
@Immutable
-public class Block extends Node implements BreakableNode, Flags<Block> {
+public class Block extends Node implements BreakableNode, Terminal, Flags<Block> {
+ private static final long serialVersionUID = 1L;
+
/** List of statements */
protected final List<Statement> statements;
@@ -53,7 +51,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
protected final Map<String, Symbol> symbols;
/** Entry label. */
- protected final Label entryLabel;
+ private final Label entryLabel;
/** Break label. */
private final Label breakLabel;
@@ -61,17 +59,13 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
/** Does the block/function need a new scope? */
protected final int flags;
- /** Flag indicating that this block needs scope */
- public static final int NEEDS_SCOPE = 1 << 0;
-
/**
- * Flag indicating whether this block needs
- * self symbol assignment at the start. This is used only for
- * blocks that are the bodies of function nodes who refer to themselves
- * by name. It causes codegen to insert a var [fn_name] = __callee__
- * at the start of the body
+ * @see JoinPredecessor
*/
- public static final int NEEDS_SELF_SYMBOL = 1 << 1;
+ private final LocalVariableConversion conversion;
+
+ /** Flag indicating that this block needs scope */
+ public static final int NEEDS_SCOPE = 1 << 0;
/**
* Is this block tagged as terminal based on its contents
@@ -80,6 +74,12 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
public static final int IS_TERMINAL = 1 << 2;
/**
+ * Is this block the eager global scope - i.e. the original program. This isn't true for the
+ * outermost level of recompiles
+ */
+ public static final int IS_GLOBAL_SCOPE = 1 << 3;
+
+ /**
* Constructor
*
* @param token token
@@ -94,7 +94,8 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
this.entryLabel = new Label("block_entry");
this.breakLabel = new Label("block_break");
final int len = statements.length;
- this.flags = (len > 0 && statements[len - 1].hasTerminalFlags()) ? IS_TERMINAL : 0;
+ this.flags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0;
+ this.conversion = null;
}
/**
@@ -108,7 +109,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
this(token, finish, statements.toArray(new Statement[statements.size()]));
}
- private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols) {
+ private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols, final LocalVariableConversion conversion) {
super(block);
this.statements = statements;
this.flags = flags;
@@ -116,11 +117,21 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
this.entryLabel = new Label(block.entryLabel);
this.breakLabel = new Label(block.breakLabel);
this.finish = finish;
+ this.conversion = conversion;
+ }
+
+ /**
+ * Is this block the outermost eager global scope - i.e. the primordial program?
+ * Used for global anchor point for scope depth computation for recompilation code
+ * @return true if outermost eager global scope
+ */
+ public boolean isGlobalScope() {
+ return getFlag(IS_GLOBAL_SCOPE);
}
/**
- * Clear the symbols in a block
- * TODO: make this immutable
+ * Clear the symbols in the block.
+ * TODO: make this immutable.
*/
public void clearSymbols() {
symbols.clear();
@@ -128,7 +139,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
- return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols));
+ return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
}
/**
@@ -140,14 +151,14 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
@Override
public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBlock(this)) {
- return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements)));
+ return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, statements)));
}
return this;
}
/**
- * Get an iterator for all the symbols defined in this block
+ * Get a copy of the list for all the symbols defined in this block
* @return symbol iterator
*/
public List<Symbol> getSymbols() {
@@ -175,9 +186,9 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
for (final Node statement : statements) {
- statement.toString(sb);
+ statement.toString(sb, printType);
sb.append(';');
}
}
@@ -217,19 +228,16 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
return isTerminal ? setFlag(lc, IS_TERMINAL) : clearFlag(lc, IS_TERMINAL);
}
- /**
- * Set the type of the return symbol in this block if present.
- * @param returnType the new type
- * @return this block
- */
- public Block setReturnType(final Type returnType) {
- final Symbol symbol = getExistingSymbol(RETURN.symbolName());
- if (symbol != null) {
- symbol.setTypeOverride(returnType);
- }
- return this;
+ @Override
+ public int getFlags() {
+ return flags;
}
+ /**
+ * Is this a terminal block, i.e. does it end control flow like ending with a throw or return?
+ *
+ * @return true if this node statement is terminal
+ */
@Override
public boolean isTerminal() {
return getFlag(IS_TERMINAL);
@@ -248,6 +256,19 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
return breakLabel;
}
+ @Override
+ public Block setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
+ }
+
/**
* Get the list of statements in this block
*
@@ -258,6 +279,25 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
}
/**
+ * Returns the number of statements in the block.
+ * @return the number of statements in the block.
+ */
+ public int getStatementCount() {
+ return statements.size();
+ }
+
+ /**
+ * Returns the line number of the first statement in the block.
+ * @return the line number of the first statement in the block, or -1 if the block has no statements.
+ */
+ public int getFirstStatementLineNumber() {
+ if(statements == null || statements.isEmpty()) {
+ return -1;
+ }
+ return statements.get(0).getLineNumber();
+ }
+
+ /**
* Reset the statement list for this block
*
* @param lc lexical context
@@ -272,7 +312,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
if (!statements.isEmpty()) {
lastFinish = statements.get(statements.size() - 1).getFinish();
}
- return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols));
+ return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols, conversion));
}
/**
@@ -295,20 +335,20 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
}
@Override
- public Block setFlags(final LexicalContext lc, int flags) {
+ public Block setFlags(final LexicalContext lc, final int flags) {
if (this.flags == flags) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols));
+ return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
}
@Override
- public Block clearFlag(final LexicalContext lc, int flag) {
+ public Block clearFlag(final LexicalContext lc, final int flag) {
return setFlags(lc, flags & ~flag);
}
@Override
- public Block setFlag(final LexicalContext lc, int flag) {
+ public Block setFlag(final LexicalContext lc, final int flag) {
return setFlags(lc, flags | flag);
}
@@ -327,7 +367,7 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols));
+ return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols, conversion));
}
/**
@@ -353,11 +393,11 @@ public class Block extends Node implements BreakableNode, Flags<Block> {
@Override
public List<Label> getLabels() {
- return Collections.singletonList(breakLabel);
+ return Collections.unmodifiableList(Arrays.asList(entryLabel, breakLabel));
}
@Override
- public Node accept(NodeVisitor<? extends LexicalContext> visitor) {
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
return Acceptor.accept(this, visitor);
}
}
diff --git a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
index 8fecddd0..7e16b5e6 100644
--- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
@@ -40,14 +40,14 @@ import java.util.List;
public class BlockLexicalContext extends LexicalContext {
/** statement stack, each block on the lexical context maintains one of these, which is
* committed to the block on pop */
- private Deque<List<Statement>> sstack = new ArrayDeque<>();
+ private final Deque<List<Statement>> sstack = new ArrayDeque<>();
/** Last non debug statement emitted in this context */
protected Statement lastStatement;
@Override
public <T extends LexicalContextNode> T push(final T node) {
- T pushed = super.push(node);
+ final T pushed = super.push(node);
if (node instanceof Block) {
sstack.push(new ArrayList<Statement>());
}
@@ -68,7 +68,7 @@ public class BlockLexicalContext extends LexicalContext {
* @param block the block to operate on
* @return a modified block.
*/
- protected Block afterSetStatements(Block block) {
+ protected Block afterSetStatements(final Block block) {
return block;
}
@@ -109,6 +109,16 @@ public class BlockLexicalContext extends LexicalContext {
}
/**
+ * Prepend a list of statement to the block being generated
+ * @param statements a list of statements to prepend
+ */
+ public void prependStatements(final List<Statement> statements) {
+ assert statements != null;
+ sstack.peek().addAll(0, statements);
+ }
+
+
+ /**
* Get the last statement that was emitted into a block
* @return the last statement emitted
*/
diff --git a/src/jdk/nashorn/internal/ir/BlockStatement.java b/src/jdk/nashorn/internal/ir/BlockStatement.java
index e790cf49..6f6a1d23 100644
--- a/src/jdk/nashorn/internal/ir/BlockStatement.java
+++ b/src/jdk/nashorn/internal/ir/BlockStatement.java
@@ -32,6 +32,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* Represents a block used as a statement.
*/
public class BlockStatement extends Statement {
+ private static final long serialVersionUID = 1L;
+
/** Block to execute. */
private final Block block;
@@ -58,7 +60,7 @@ public class BlockStatement extends Statement {
* @return a block statement with the new statements. It will have the line number, token, and finish of the
* original statement.
*/
- public static Statement createReplacement(final Statement stmt, final List<Statement> newStmts) {
+ public static BlockStatement createReplacement(final Statement stmt, final List<Statement> newStmts) {
return createReplacement(stmt, stmt.getFinish(), newStmts);
}
@@ -70,7 +72,7 @@ public class BlockStatement extends Statement {
* @return a block statement with the new statements. It will have the line number, and token of the
* original statement.
*/
- public static Statement createReplacement(final Statement stmt, int finish, final List<Statement> newStmts) {
+ public static BlockStatement createReplacement(final Statement stmt, final int finish, final List<Statement> newStmts) {
return new BlockStatement(stmt.getLineNumber(), new Block(stmt.getToken(), finish, newStmts));
}
@@ -89,8 +91,8 @@ public class BlockStatement extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
- block.toString(sb);
+ public void toString(final StringBuilder sb, final boolean printType) {
+ block.toString(sb, printType);
}
/**
diff --git a/src/jdk/nashorn/internal/ir/BreakNode.java b/src/jdk/nashorn/internal/ir/BreakNode.java
index 2b8fbd83..4cbf4c02 100644
--- a/src/jdk/nashorn/internal/ir/BreakNode.java
+++ b/src/jdk/nashorn/internal/ir/BreakNode.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.ir;
+import jdk.nashorn.internal.codegen.Label;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -32,9 +33,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation for {@code break} statements.
*/
@Immutable
-public final class BreakNode extends Statement {
-
- private final IdentNode label;
+public final class BreakNode extends JumpStatement {
+ private static final long serialVersionUID = 1L;
/**
* Constructor
@@ -42,22 +42,16 @@ public final class BreakNode extends Statement {
* @param lineNumber line number
* @param token token
* @param finish finish
- * @param label label for break or null if none
+ * @param labelName label name for break or null if none
*/
- public BreakNode(final int lineNumber, final long token, final int finish, final IdentNode label) {
- super(lineNumber, token, finish);
- this.label = label;
+ public BreakNode(final int lineNumber, final long token, final int finish, final String labelName) {
+ super(lineNumber, token, finish, labelName);
}
- @Override
- public boolean hasGoto() {
- return true;
+ private BreakNode(final BreakNode breakNode, final LocalVariableConversion conversion) {
+ super(breakNode, conversion);
}
- /**
- * Assist in IR navigation.
- * @param visitor IR navigating visitor.
- */
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBreakNode(this)) {
@@ -67,21 +61,23 @@ public final class BreakNode extends Statement {
return this;
}
- /**
- * Get the label for this break node
- * @return label, or null if none
- */
- public IdentNode getLabel() {
- return label;
+ @Override
+ JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+ return new BreakNode(this, conversion);
}
@Override
- public void toString(final StringBuilder sb) {
- sb.append("break");
+ String getStatementName() {
+ return "break";
+ }
- if (label != null) {
- sb.append(' ');
- label.toString(sb);
- }
+ @Override
+ public BreakableNode getTarget(final LexicalContext lc) {
+ return lc.getBreakable(getLabelName());
+ }
+
+ @Override
+ public Label getTargetLabel(final BreakableNode target) {
+ return target.getBreakLabel();
}
}
diff --git a/src/jdk/nashorn/internal/ir/BreakableNode.java b/src/jdk/nashorn/internal/ir/BreakableNode.java
index 0d12b7cd..160a1f63 100644
--- a/src/jdk/nashorn/internal/ir/BreakableNode.java
+++ b/src/jdk/nashorn/internal/ir/BreakableNode.java
@@ -25,14 +25,13 @@
package jdk.nashorn.internal.ir;
-import java.util.List;
import jdk.nashorn.internal.codegen.Label;
/**
* This class represents a node from which control flow can execute
* a {@code break} statement
*/
-public interface BreakableNode extends LexicalContextNode {
+public interface BreakableNode extends LexicalContextNode, JoinPredecessor, Labels {
/**
* Ensure that any labels in this breakable node are unique so
* that new jumps won't go to old parts of the tree. Used for
@@ -56,11 +55,4 @@ public interface BreakableNode extends LexicalContextNode {
*/
public Label getBreakLabel();
- /**
- * Return the labels associated with this node. Breakable nodes that
- * aren't LoopNodes only have a break label - the location immediately
- * afterwards the node in code
- * @return list of labels representing locations around this node
- */
- public List<Label> getLabels();
}
diff --git a/src/jdk/nashorn/internal/ir/BreakableStatement.java b/src/jdk/nashorn/internal/ir/BreakableStatement.java
index fa74454e..7e1afaf0 100644
--- a/src/jdk/nashorn/internal/ir/BreakableStatement.java
+++ b/src/jdk/nashorn/internal/ir/BreakableStatement.java
@@ -32,10 +32,13 @@ import jdk.nashorn.internal.ir.annotations.Immutable;
@Immutable
abstract class BreakableStatement extends LexicalContextStatement implements BreakableNode {
+ private static final long serialVersionUID = 1L;
/** break label. */
protected final Label breakLabel;
+ final LocalVariableConversion conversion;
+
/**
* Constructor
*
@@ -47,16 +50,19 @@ abstract class BreakableStatement extends LexicalContextStatement implements Bre
protected BreakableStatement(final int lineNumber, final long token, final int finish, final Label breakLabel) {
super(lineNumber, token, finish);
this.breakLabel = breakLabel;
+ this.conversion = null;
}
/**
* Copy constructor
*
* @param breakableNode source node
+ * @param conversion the potentially new local variable conversion
*/
- protected BreakableStatement(final BreakableStatement breakableNode) {
+ protected BreakableStatement(final BreakableStatement breakableNode, final LocalVariableConversion conversion) {
super(breakableNode);
this.breakLabel = new Label(breakableNode.getBreakLabel());
+ this.conversion = conversion;
}
/**
@@ -86,6 +92,21 @@ abstract class BreakableStatement extends LexicalContextStatement implements Bre
*/
@Override
public List<Label> getLabels() {
- return Collections.singletonList(breakLabel);
+ return Collections.unmodifiableList(Collections.singletonList(breakLabel));
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return setLocalVariableConversionChanged(lc, conversion);
}
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
+ }
+
+ abstract JoinPredecessor setLocalVariableConversionChanged(LexicalContext lc, LocalVariableConversion conversion);
}
diff --git a/src/jdk/nashorn/internal/ir/CallNode.java b/src/jdk/nashorn/internal/ir/CallNode.java
index 0d38f241..72eab68b 100644
--- a/src/jdk/nashorn/internal/ir/CallNode.java
+++ b/src/jdk/nashorn/internal/ir/CallNode.java
@@ -25,8 +25,12 @@
package jdk.nashorn.internal.ir;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.io.Serializable;
import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -36,7 +40,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation for a function call.
*/
@Immutable
-public final class CallNode extends LexicalContextExpression {
+public final class CallNode extends LexicalContextExpression implements Optimistic {
+ private static final long serialVersionUID = 1L;
/** Function identifier or function body. */
private final Expression function;
@@ -45,71 +50,53 @@ public final class CallNode extends LexicalContextExpression {
private final List<Expression> args;
/** Is this a "new" operation */
- public static final int IS_NEW = 0x1;
+ private static final int IS_NEW = 1 << 0;
+
+ /** Can this be a Function.call? */
+ private static final int IS_APPLY_TO_CALL = 1 << 1;
private final int flags;
private final int lineNumber;
+ private final int programPoint;
+
+ private final Type optimisticType;
+
/**
* Arguments to be passed to builtin {@code eval} function
*/
- public static class EvalArgs {
- /** evaluated code */
- private final Expression code;
-
- /** 'this' passed to evaluated code */
- private final IdentNode evalThis;
+ public static class EvalArgs implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final List<Expression> args;
/** location string for the eval call */
private final String location;
- /** is this call from a strict context? */
- private final boolean strictMode;
-
/**
* Constructor
*
- * @param code code to evaluate
- * @param evalThis this node
- * @param location location for the eval call
- * @param strictMode is this a call from a strict context?
+ * @param args arguments to eval
+ * @param location location for the eval call
*/
- public EvalArgs(final Expression code, final IdentNode evalThis, final String location, final boolean strictMode) {
- this.code = code;
- this.evalThis = evalThis;
+ public EvalArgs(final List<Expression> args, final String location) {
+ this.args = args;
this.location = location;
- this.strictMode = strictMode;
}
/**
* Return the code that is to be eval:ed by this eval function
* @return code as an AST node
*/
- public Expression getCode() {
- return code;
+ public List<Expression> getArgs() {
+ return Collections.unmodifiableList(args);
}
- private EvalArgs setCode(final Expression code) {
- if (this.code == code) {
+ private EvalArgs setArgs(final List<Expression> args) {
+ if (this.args == args) {
return this;
}
- return new EvalArgs(code, evalThis, location, strictMode);
- }
-
- /**
- * Get the {@code this} symbol used to invoke this eval call
- * @return the {@code this} symbol
- */
- public IdentNode getThis() {
- return this.evalThis;
- }
-
- private EvalArgs setThis(final IdentNode evalThis) {
- if (this.evalThis == evalThis) {
- return this;
- }
- return new EvalArgs(code, evalThis, location, strictMode);
+ return new EvalArgs(args, location);
}
/**
@@ -119,14 +106,6 @@ public final class CallNode extends LexicalContextExpression {
public String getLocation() {
return this.location;
}
-
- /**
- * Check whether this eval call is executed in strict mode
- * @return true if executed in strict mode, false otherwise
- */
- public boolean getStrictMode() {
- return this.strictMode;
- }
}
/** arguments for 'eval' call. Non-null only if this call node is 'eval' */
@@ -141,24 +120,29 @@ public final class CallNode extends LexicalContextExpression {
* @param finish finish
* @param function the function to call
* @param args args to the call
+ * @param isNew true if this is a constructor call with the "new" keyword
*/
- public CallNode(final int lineNumber, final long token, final int finish, final Expression function, final List<Expression> args) {
+ public CallNode(final int lineNumber, final long token, final int finish, final Expression function, final List<Expression> args, final boolean isNew) {
super(token, finish);
- this.function = function;
- this.args = args;
- this.flags = 0;
- this.evalArgs = null;
- this.lineNumber = lineNumber;
+ this.function = function;
+ this.args = args;
+ this.flags = isNew ? IS_NEW : 0;
+ this.evalArgs = null;
+ this.lineNumber = lineNumber;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.optimisticType = null;
}
- private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final EvalArgs evalArgs) {
+ private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final Type optimisticType, final EvalArgs evalArgs, final int programPoint) {
super(callNode);
this.lineNumber = callNode.lineNumber;
this.function = function;
this.args = args;
this.flags = flags;
this.evalArgs = evalArgs;
+ this.programPoint = programPoint;
+ this.optimisticType = optimisticType;
}
/**
@@ -170,8 +154,16 @@ public final class CallNode extends LexicalContextExpression {
}
@Override
- public Type getType() {
- return function instanceof FunctionNode ? ((FunctionNode)function).getReturnType() : Type.OBJECT;
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return optimisticType == null ? Type.OBJECT : optimisticType;
+ }
+
+ @Override
+ public Optimistic setType(final Type optimisticType) {
+ if (this.optimisticType == optimisticType) {
+ return this;
+ }
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
}
/**
@@ -186,15 +178,13 @@ public final class CallNode extends LexicalContextExpression {
if (visitor.enterCallNode(this)) {
final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
setFunction((Expression)function.accept(visitor)).
- setArgs(Node.accept(visitor, Expression.class, args)).
- setFlags(flags).
+ setArgs(Node.accept(visitor, args)).
setEvalArgs(evalArgs == null ?
null :
- evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
- setThis((IdentNode)evalArgs.getThis().accept(visitor))));
+ evalArgs.setArgs(Node.accept(visitor, evalArgs.getArgs()))));
// Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
// setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
- if(this != newCallNode) {
+ if (this != newCallNode) {
return Node.replaceInLexicalContext(lc, this, newCallNode);
}
}
@@ -203,8 +193,19 @@ public final class CallNode extends LexicalContextExpression {
}
@Override
- public void toString(final StringBuilder sb) {
- function.toString(sb);
+ public void toString(final StringBuilder sb, final boolean printType) {
+ if (printType) {
+ optimisticTypeToString(sb);
+ }
+
+ final StringBuilder fsb = new StringBuilder();
+ function.toString(fsb, printType);
+
+ if (isApplyToCall()) {
+ sb.append(fsb.toString().replace("apply", "[apply => call]"));
+ } else {
+ sb.append(fsb);
+ }
sb.append('(');
@@ -217,7 +218,7 @@ public final class CallNode extends LexicalContextExpression {
first = false;
}
- arg.toString(sb);
+ arg.toString(sb, printType);
}
sb.append(')');
@@ -234,12 +235,13 @@ public final class CallNode extends LexicalContextExpression {
/**
* Reset the arguments for the call
* @param args new arguments list
+ * @return new callnode, or same if unchanged
*/
- private CallNode setArgs(final List<Expression> args) {
+ public CallNode setArgs(final List<Expression> args) {
if (this.args == args) {
return this;
}
- return new CallNode(this, function, args, flags, evalArgs);
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
}
/**
@@ -261,7 +263,7 @@ public final class CallNode extends LexicalContextExpression {
if (this.evalArgs == evalArgs) {
return this;
}
- return new CallNode(this, function, args, flags, evalArgs);
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
}
/**
@@ -273,6 +275,23 @@ public final class CallNode extends LexicalContextExpression {
}
/**
+ * Is this an apply call that we optimistically should try to turn into
+ * a call instead
+ * @return true if apply to call
+ */
+ public boolean isApplyToCall() {
+ return (flags & IS_APPLY_TO_CALL) != 0;
+ }
+
+ /**
+ * Flag this call node as one that tries to call call instead of apply
+ * @return new call node with changed flags, if not already flagged as apply to call, then the same node
+ */
+ public CallNode setIsApplyToCall() {
+ return setFlags(flags | IS_APPLY_TO_CALL);
+ }
+
+ /**
* Return the function expression that this call invokes
* @return the function
*/
@@ -289,7 +308,7 @@ public final class CallNode extends LexicalContextExpression {
if (this.function == function) {
return this;
}
- return new CallNode(this, function, args, flags, evalArgs);
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
}
/**
@@ -297,21 +316,41 @@ public final class CallNode extends LexicalContextExpression {
* @return true if this a new operation
*/
public boolean isNew() {
- return (flags & IS_NEW) == IS_NEW;
- }
-
- /**
- * Flag this call as a new operation
- * @return same node or new one on state change
- */
- public CallNode setIsNew() {
- return setFlags(IS_NEW);
+ return (flags & IS_NEW) != 0;
}
private CallNode setFlags(final int flags) {
if (this.flags == flags) {
return this;
}
- return new CallNode(this, function, args, flags, evalArgs);
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ @Override
+ public CallNode setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ return Type.INT;
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return true;
}
}
diff --git a/src/jdk/nashorn/internal/ir/CaseNode.java b/src/jdk/nashorn/internal/ir/CaseNode.java
index c809058a..48f96184 100644
--- a/src/jdk/nashorn/internal/ir/CaseNode.java
+++ b/src/jdk/nashorn/internal/ir/CaseNode.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.ir;
+import java.util.Collections;
+import java.util.List;
import jdk.nashorn.internal.codegen.Label;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -34,7 +36,9 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* Case nodes are not BreakableNodes, but the SwitchNode is
*/
@Immutable
-public final class CaseNode extends Node {
+public final class CaseNode extends Node implements JoinPredecessor, Labels, Terminal {
+ private static final long serialVersionUID = 1L;
+
/** Test expression. */
private final Expression test;
@@ -45,6 +49,11 @@ public final class CaseNode extends Node {
private final Label entry;
/**
+ * @see JoinPredecessor
+ */
+ private final LocalVariableConversion conversion;
+
+ /**
* Constructors
*
* @param token token
@@ -58,16 +67,23 @@ public final class CaseNode extends Node {
this.test = test;
this.body = body;
this.entry = new Label("entry");
+ this.conversion = null;
}
- CaseNode(final CaseNode caseNode, final Expression test, final Block body) {
+ CaseNode(final CaseNode caseNode, final Expression test, final Block body, final LocalVariableConversion conversion) {
super(caseNode);
this.test = test;
this.body = body;
this.entry = new Label(caseNode.entry);
+ this.conversion = conversion;
}
+ /**
+ * Is this a terminal case node, i.e. does it end control flow like having a throw or return?
+ *
+ * @return true if this node statement is terminal
+ */
@Override
public boolean isTerminal() {
return body.isTerminal();
@@ -90,10 +106,10 @@ public final class CaseNode extends Node {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printTypes) {
if (test != null) {
sb.append("case ");
- test.toString(sb);
+ test.toString(sb, printTypes);
sb.append(':');
} else {
sb.append("default:");
@@ -133,13 +149,31 @@ public final class CaseNode extends Node {
if (this.test == test) {
return this;
}
- return new CaseNode(this, test, body);
+ return new CaseNode(this, test, body, conversion);
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new CaseNode(this, test, body, conversion);
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
private CaseNode setBody(final Block body) {
if (this.body == body) {
return this;
}
- return new CaseNode(this, test, body);
+ return new CaseNode(this, test, body, conversion);
+ }
+
+ @Override
+ public List<Label> getLabels() {
+ return Collections.unmodifiableList(Collections.singletonList(entry));
}
}
diff --git a/src/jdk/nashorn/internal/ir/CatchNode.java b/src/jdk/nashorn/internal/ir/CatchNode.java
index ba640a52..80ca3a50 100644
--- a/src/jdk/nashorn/internal/ir/CatchNode.java
+++ b/src/jdk/nashorn/internal/ir/CatchNode.java
@@ -33,6 +33,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class CatchNode extends Statement {
+ private static final long serialVersionUID = 1L;
+
/** Exception identifier. */
private final IdentNode exception;
@@ -42,10 +44,7 @@ public final class CatchNode extends Statement {
/** Catch body. */
private final Block body;
- private final int flags;
-
- /** Is this block a synthethic rethrow created by finally inlining? */
- public static final int IS_SYNTHETIC_RETHROW = 1;
+ private final boolean isSyntheticRethrow;
/**
* Constructors
@@ -56,22 +55,24 @@ public final class CatchNode extends Statement {
* @param exception variable name of exception
* @param exceptionCondition exception condition
* @param body catch body
- * @param flags flags
+ * @param isSyntheticRethrow true if this node is a synthetically generated rethrow node.
*/
- public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
+ public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception,
+ final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) {
super(lineNumber, token, finish);
- this.exception = exception;
+ this.exception = exception == null ? null : exception.setIsInitializedHere();
this.exceptionCondition = exceptionCondition;
this.body = body;
- this.flags = flags;
+ this.isSyntheticRethrow = isSyntheticRethrow;
}
- private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
+ private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition,
+ final Block body, final boolean isSyntheticRethrow) {
super(catchNode);
this.exception = exception;
this.exceptionCondition = exceptionCondition;
this.body = body;
- this.flags = flags;
+ this.isSyntheticRethrow = isSyntheticRethrow;
}
/**
@@ -96,13 +97,13 @@ public final class CatchNode extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printTypes) {
sb.append(" catch (");
- exception.toString(sb);
+ exception.toString(sb, printTypes);
if (exceptionCondition != null) {
sb.append(" if ");
- exceptionCondition.toString(sb);
+ exceptionCondition.toString(sb, printTypes);
}
sb.append(')');
}
@@ -132,7 +133,7 @@ public final class CatchNode extends Statement {
if (this.exceptionCondition == exceptionCondition) {
return this;
}
- return new CatchNode(this, exception, exceptionCondition, body, flags);
+ return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
}
/**
@@ -152,14 +153,14 @@ public final class CatchNode extends Statement {
if (this.exception == exception) {
return this;
}
- return new CatchNode(this, exception, exceptionCondition, body, flags);
+ return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
}
private CatchNode setBody(final Block body) {
if (this.body == body) {
return this;
}
- return new CatchNode(this, exception, exceptionCondition, body, flags);
+ return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
}
/**
@@ -170,7 +171,6 @@ public final class CatchNode extends Statement {
* @return true if a finally synthetic rethrow
*/
public boolean isSyntheticRethrow() {
- return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
+ return isSyntheticRethrow;
}
-
}
diff --git a/src/jdk/nashorn/internal/ir/CompileUnitHolder.java b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java
new file mode 100644
index 00000000..27d69d53
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.CompileUnit;
+
+/**
+ * Marker interface for things in the IR that can hold compile units.
+ * {@link CompileUnit}
+ */
+public interface CompileUnitHolder {
+ /**
+ * Return the compile unit held by this instance
+ * @return compile unit
+ */
+ public CompileUnit getCompileUnit();
+}
diff --git a/src/jdk/nashorn/internal/ir/ContinueNode.java b/src/jdk/nashorn/internal/ir/ContinueNode.java
index 579414a9..c58531bd 100644
--- a/src/jdk/nashorn/internal/ir/ContinueNode.java
+++ b/src/jdk/nashorn/internal/ir/ContinueNode.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.ir;
+import jdk.nashorn.internal.codegen.Label;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -32,9 +33,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation for CONTINUE statements.
*/
@Immutable
-public class ContinueNode extends Statement {
-
- private IdentNode label;
+public class ContinueNode extends JumpStatement {
+ private static final long serialVersionUID = 1L;
/**
* Constructor
@@ -42,16 +42,14 @@ public class ContinueNode extends Statement {
* @param lineNumber line number
* @param token token
* @param finish finish
- * @param label label for break or null if none
+ * @param labelName label name for continue or null if none
*/
- public ContinueNode(final int lineNumber, final long token, final int finish, final IdentNode label) {
- super(lineNumber, token, finish);
- this.label = label;
+ public ContinueNode(final int lineNumber, final long token, final int finish, final String labelName) {
+ super(lineNumber, token, finish, labelName);
}
- @Override
- public boolean hasGoto() {
- return true;
+ private ContinueNode(final ContinueNode continueNode, final LocalVariableConversion conversion) {
+ super(continueNode, conversion);
}
@Override
@@ -63,22 +61,24 @@ public class ContinueNode extends Statement {
return this;
}
- /**
- * Get the label for this break node
- * @return label, or null if none
- */
- public IdentNode getLabel() {
- return label;
+ @Override
+ JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+ return new ContinueNode(this, conversion);
}
@Override
- public void toString(final StringBuilder sb) {
- sb.append("continue");
+ String getStatementName() {
+ return "continue";
+ }
- if (label != null) {
- sb.append(' ');
- label.toString(sb);
- }
+
+ @Override
+ public BreakableNode getTarget(final LexicalContext lc) {
+ return lc.getContinueTo(getLabelName());
}
-}
+ @Override
+ public Label getTargetLabel(final BreakableNode target) {
+ return ((LoopNode)target).getContinueLabel();
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/EmptyNode.java b/src/jdk/nashorn/internal/ir/EmptyNode.java
index aa86f2f8..2c9d976d 100644
--- a/src/jdk/nashorn/internal/ir/EmptyNode.java
+++ b/src/jdk/nashorn/internal/ir/EmptyNode.java
@@ -33,6 +33,7 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class EmptyNode extends Statement {
+ private static final long serialVersionUID = 1L;
/**
* Constructor
@@ -64,7 +65,7 @@ public final class EmptyNode extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printTypes) {
sb.append(';');
}
diff --git a/src/jdk/nashorn/internal/ir/Expression.java b/src/jdk/nashorn/internal/ir/Expression.java
index f8074fe4..78523412 100644
--- a/src/jdk/nashorn/internal/ir/Expression.java
+++ b/src/jdk/nashorn/internal/ir/Expression.java
@@ -25,7 +25,9 @@
package jdk.nashorn.internal.ir;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* Common superclass for all expression nodes. Expression nodes can have
@@ -33,79 +35,140 @@ import jdk.nashorn.internal.codegen.types.Type;
*
*/
public abstract class Expression extends Node {
- private Symbol symbol;
+ private static final long serialVersionUID = 1L;
- Expression(long token, int start, int finish) {
+ static final String OPT_IDENTIFIER = "%";
+
+ private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+ @Override
+ public Type apply(final Symbol t) {
+ return null;
+ }
+ };
+
+ Expression(final long token, final int start, final int finish) {
super(token, start, finish);
}
- Expression(long token, int finish) {
+ Expression(final long token, final int finish) {
super(token, finish);
}
- Expression(Expression expr) {
+ Expression(final Expression expr) {
super(expr);
- this.symbol = expr.symbol;
}
/**
- * Return the Symbol the compiler has assigned to this Node. The symbol
- * is the place where it's expression value is stored after evaluation
+ * Returns the type of the expression.
*
- * @return the symbol
+ * @return the type of the expression.
*/
- public Symbol getSymbol() {
- return symbol;
+ public final Type getType() {
+ return getType(UNKNOWN_LOCALS);
}
/**
- * Assign a symbol to this node. See {@link Expression#getSymbol()} for explanation
- * of what a symbol is
+ * Returns the type of the expression under the specified symbol-to-type mapping. By default delegates to
+ * {@link #getType()} but expressions whose type depends on their subexpressions' types and expressions whose type
+ * depends on symbol type ({@link IdentNode}) will have a special implementation.
+ * @param localVariableTypes a mapping from symbols to their types, used for type calculation.
+ * @return the type of the expression under the specified symbol-to-type mapping.
+ */
+ public abstract Type getType(final Function<Symbol, Type> localVariableTypes);
+
+ /**
+ * Returns {@code true} if this expression depends exclusively on state that is constant
+ * or local to the currently running function and thus inaccessible to other functions.
+ * This implies that a local expression must not call any other functions (neither directly
+ * nor implicitly through a getter, setter, or object-to-primitive type conversion).
*
- * @param lc lexical context
- * @param symbol the symbol
- * @return new node
+ * @return true if this expression does not depend on state shared with other functions.
*/
- public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
- if (this.symbol == symbol) {
- return this;
- }
- final Expression newExpr = (Expression)clone();
- newExpr.symbol = symbol;
- return newExpr;
+ public boolean isLocal() {
+ return false;
}
/**
- * Check if the expression has a type. The default behavior is to go into the symbol
- * and check the symbol type, but there may be overrides, for example in
- * getters that require a different type than the internal representation
- *
- * @return true if a type exists
+ * Is this a self modifying assignment?
+ * @return true if self modifying, e.g. a++, or a*= 17
*/
- public boolean hasType() {
- return getSymbol() != null;
+ public boolean isSelfModifying() {
+ return false;
}
/**
- * Returns the type of the expression. Typically this is the symbol type. No types
- * are stored in the expression itself, unless it implements TypeOverride.
+ * Returns widest operation type of this operation.
*
- * @return the type of the node.
+ * @return the widest type for this operation
*/
- public Type getType() {
- assert hasType() : this + " has no type";
- return symbol.getSymbolType();
+ public Type getWidestOperationType() {
+ return Type.OBJECT;
}
/**
- * Returns {@code true} if this expression depends exclusively on state that is constant
- * or local to the currently running function and thus inaccessible to other functions.
- * This implies that a local expression must not call any other functions (neither directly
- * nor implicitly through a getter, setter, or object-to-primitive type conversion).
- *
- * @return true if this expression does not depend on state shared with other functions.
+ * Returns true if the type of this expression is narrower than its widest operation type (thus, it is
+ * optimistically typed).
+ * @return true if this expression is optimistically typed.
*/
- public boolean isLocal() {
+ public final boolean isOptimistic() {
+ return getType().narrowerThan(getWidestOperationType());
+ }
+
+ void optimisticTypeToString(final StringBuilder sb) {
+ optimisticTypeToString(sb, isOptimistic());
+ }
+
+ void optimisticTypeToString(final StringBuilder sb, final boolean optimistic) {
+ sb.append('{');
+ final Type type = getType();
+ final String desc = type == Type.UNDEFINED ? "U" : type.getDescriptor();
+
+ sb.append(desc.charAt(desc.length() - 1) == ';' ? "O" : desc);
+ if (isOptimistic() && optimistic) {
+ sb.append(OPT_IDENTIFIER);
+ final int pp = ((Optimistic)this).getProgramPoint();
+ if (UnwarrantedOptimismException.isValid(pp)) {
+ sb.append('_').append(pp);
+ }
+ }
+ sb.append('}');
+ }
+
+ /**
+ * Returns true if the runtime value of this expression is always false when converted to boolean as per ECMAScript
+ * ToBoolean conversion. Used in control flow calculations.
+ * @return true if this expression's runtime value converted to boolean is always false.
+ */
+ public boolean isAlwaysFalse() {
return false;
}
+
+ /**
+ * Returns true if the runtime value of this expression is always true when converted to boolean as per ECMAScript
+ * ToBoolean conversion. Used in control flow calculations.
+ * @return true if this expression's runtime value converted to boolean is always true.
+ */
+ public boolean isAlwaysTrue() {
+ return false;
+ }
+
+ /**
+ * Returns true if the expression is not null and {@link #isAlwaysFalse()}.
+ * @param test a test expression used as a predicate of a branch or a loop.
+ * @return true if the expression is not null and {@link #isAlwaysFalse()}.
+ */
+ public static boolean isAlwaysFalse(final Expression test) {
+ return test != null && test.isAlwaysFalse();
+ }
+
+
+ /**
+ * Returns true if the expression is null or {@link #isAlwaysTrue()}. Null is considered to be always true as a
+ * for loop with no test is equivalent to a for loop with always-true test.
+ * @param test a test expression used as a predicate of a branch or a loop.
+ * @return true if the expression is null or {@link #isAlwaysFalse()}.
+ */
+ public static boolean isAlwaysTrue(final Expression test) {
+ return test == null || test.isAlwaysTrue();
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/ExpressionStatement.java b/src/jdk/nashorn/internal/ir/ExpressionStatement.java
index 8b118a2b..b8e54280 100644
--- a/src/jdk/nashorn/internal/ir/ExpressionStatement.java
+++ b/src/jdk/nashorn/internal/ir/ExpressionStatement.java
@@ -35,6 +35,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class ExpressionStatement extends Statement {
+ private static final long serialVersionUID = 1L;
+
/** Expression to execute. */
private final Expression expression;
@@ -57,11 +59,6 @@ public final class ExpressionStatement extends Statement {
}
@Override
- public boolean isTerminal() {
- return expression.isTerminal();
- }
-
- @Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterExpressionStatement(this)) {
return visitor.leaveExpressionStatement(setExpression((Expression)expression.accept(visitor)));
@@ -71,8 +68,8 @@ public final class ExpressionStatement extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
- expression.toString(sb);
+ public void toString(final StringBuilder sb, final boolean printTypes) {
+ expression.toString(sb, printTypes);
}
/**
diff --git a/src/jdk/nashorn/internal/ir/Flags.java b/src/jdk/nashorn/internal/ir/Flags.java
index 94a21098..fb4b5de9 100644
--- a/src/jdk/nashorn/internal/ir/Flags.java
+++ b/src/jdk/nashorn/internal/ir/Flags.java
@@ -37,6 +37,12 @@ package jdk.nashorn.internal.ir;
public interface Flags<T extends LexicalContextNode> {
/**
+ * Get all flags of a LexicalContextNode
+ * @return flags
+ */
+ public int getFlags();
+
+ /**
* Check if a flag is set in a lexical context node
* @param flag flag to check
* @return flags
diff --git a/src/jdk/nashorn/internal/ir/ForNode.java b/src/jdk/nashorn/internal/ir/ForNode.java
index 8130e23b..ef6f11db 100644
--- a/src/jdk/nashorn/internal/ir/ForNode.java
+++ b/src/jdk/nashorn/internal/ir/ForNode.java
@@ -33,23 +33,26 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class ForNode extends LoopNode {
- /** Initialize expression. */
+ private static final long serialVersionUID = 1L;
+
+ /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
+ * for-in statement. */
private final Expression init;
- /** Test expression. */
- private final Expression modify;
+ /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */
+ private final JoinPredecessorExpression modify;
/** Iterator symbol. */
private Symbol iterator;
- /** Is this a normal for loop? */
- public static final int IS_FOR = 1 << 0;
-
/** Is this a normal for in loop? */
- public static final int IS_FOR_IN = 1 << 1;
+ public static final int IS_FOR_IN = 1 << 0;
/** Is this a normal for each in loop? */
- public static final int IS_FOR_EACH = 1 << 2;
+ public static final int IS_FOR_EACH = 1 << 1;
+
+ /** Does this loop need a per-iteration scope because its init contain a LET declaration? */
+ public static final int PER_ITERATION_SCOPE = 1 << 2;
private final int flags;
@@ -59,30 +62,30 @@ public final class ForNode extends LoopNode {
* @param lineNumber line number
* @param token token
* @param finish finish
- * @param init initialization expression
- * @param test test
* @param body body
- * @param modify modify
* @param flags flags
*/
- public ForNode(final int lineNumber, final long token, final int finish, final Expression init, final Expression test, final Block body, final Expression modify, final int flags) {
- super(lineNumber, token, finish, test, body, false);
- this.init = init;
- this.modify = modify;
+ public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags) {
+ super(lineNumber, token, finish, body, false);
this.flags = flags;
+ this.init = null;
+ this.modify = null;
}
- private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) {
- super(forNode, test, body, controlFlowEscapes);
+ private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
+ final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+ super(forNode, test, body, controlFlowEscapes, conversion);
this.init = init;
this.modify = modify;
this.flags = flags;
- this.iterator = forNode.iterator; //TODO is this acceptable? symbols are never cloned, just copied as references
+ // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally
+ // is executed.
+ this.iterator = forNode.iterator;
}
@Override
- public Node ensureUniqueLabels(LexicalContext lc) {
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ public Node ensureUniqueLabels(final LexicalContext lc) {
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
@Override
@@ -90,8 +93,8 @@ public final class ForNode extends LoopNode {
if (visitor.enterForNode(this)) {
return visitor.leaveForNode(
setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
- setTest(lc, test == null ? null : (Expression)test.accept(visitor)).
- setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)).
+ setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)).
+ setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)).
setBody(lc, (Block)body.accept(visitor)));
}
@@ -99,24 +102,25 @@ public final class ForNode extends LoopNode {
}
@Override
- public void toString(final StringBuilder sb) {
- sb.append("for (");
+ public void toString(final StringBuilder sb, final boolean printTypes) {
+ sb.append("for");
+ LocalVariableConversion.toString(conversion, sb).append(' ');
if (isForIn()) {
- init.toString(sb);
+ init.toString(sb, printTypes);
sb.append(" in ");
- modify.toString(sb);
+ modify.toString(sb, printTypes);
} else {
if (init != null) {
- init.toString(sb);
+ init.toString(sb, printTypes);
}
sb.append("; ");
if (test != null) {
- test.toString(sb);
+ test.toString(sb, printTypes);
}
sb.append("; ");
if (modify != null) {
- modify.toString(sb);
+ modify.toString(sb, printTypes);
}
}
@@ -154,7 +158,7 @@ public final class ForNode extends LoopNode {
if (this.init == init) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
/**
@@ -212,7 +216,7 @@ public final class ForNode extends LoopNode {
* Get the modification expression for this ForNode
* @return the modification expression
*/
- public Expression getModify() {
+ public JoinPredecessorExpression getModify() {
return modify;
}
@@ -222,24 +226,19 @@ public final class ForNode extends LoopNode {
* @param modify new modification expression
* @return new for node if changed or existing if not
*/
- public ForNode setModify(final LexicalContext lc, final Expression modify) {
+ public ForNode setModify(final LexicalContext lc, final JoinPredecessorExpression modify) {
if (this.modify == modify) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
@Override
- public Expression getTest() {
- return test;
- }
-
- @Override
- public ForNode setTest(final LexicalContext lc, final Expression test) {
+ public ForNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
if (this.test == test) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
@Override
@@ -252,7 +251,7 @@ public final class ForNode extends LoopNode {
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
@Override
@@ -260,14 +259,32 @@ public final class ForNode extends LoopNode {
if (this.controlFlowEscapes == controlFlowEscapes) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
}
private ForNode setFlags(final LexicalContext lc, final int flags) {
if (this.flags == flags) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ }
+
+ @Override
+ JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+ return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+ }
+
+ @Override
+ public boolean hasPerIterationScope() {
+ return (flags & PER_ITERATION_SCOPE) != 0;
}
+ /**
+ * Set the per-iteration-scope flag on this node.
+ * @param lc lexical context
+ * @return the node with flag set
+ */
+ public ForNode setPerIterationScope(final LexicalContext lc) {
+ return setFlags(lc, flags | PER_ITERATION_SCOPE);
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/FunctionCall.java b/src/jdk/nashorn/internal/ir/FunctionCall.java
index 73a6c625..22bf37d1 100644
--- a/src/jdk/nashorn/internal/ir/FunctionCall.java
+++ b/src/jdk/nashorn/internal/ir/FunctionCall.java
@@ -26,14 +26,18 @@
package jdk.nashorn.internal.ir;
/**
- * Interface used by AccessNodes, IndexNodes and IdentNodes to signal
- * that they are function calls
+ * Interface used by AccessNodes, IndexNodes and IdentNodes to signal that when evaluated, their value will be treated
+ * as a function and immediately invoked, e.g. {@code foo()}, {@code foo.bar()} or {@code foo[bar]()}. Used to customize
+ * the priority of composite dynamic operations when emitting {@code INVOKEDYNAMIC} instructions that implement them,
+ * namely prioritize {@code getMethod} over {@code getElem} or {@code getProp}. An access or ident node with isFunction
+ * set to true will be emitted as {@code dyn:getMethod|getProp|getElem} while one with it set to false will be emitted
+ * as {@code dyn:getProp|getElem|getMethod}. Similarly, an index node with isFunction set to true will be emitted as
+ * {@code dyn:getMethod|getElem|getProp} while the one set to false will be emitted as {@code dyn:getElem|getProp|getMethod}.
*/
public interface FunctionCall {
/**
- * Return true if this function call implementor is a function
- *
- * @return true if implements a function call
+ * Returns true if the value of this expression will be treated as a function and immediately invoked.
+ * @return true if the value of this expression will be treated as a function and immediately invoked.
*/
public boolean isFunction();
}
diff --git a/src/jdk/nashorn/internal/ir/FunctionNode.java b/src/jdk/nashorn/internal/ir/FunctionNode.java
index a0f6a788..0806fea9 100644
--- a/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -25,12 +25,19 @@
package jdk.nashorn.internal.ir;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
+
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.function.Function;
+import jdk.nashorn.internal.AssertsEnabled;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -39,6 +46,7 @@ import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.UserAccessorProperty;
@@ -48,7 +56,8 @@ import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
* IR representation for function (or script.)
*/
@Immutable
-public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
+public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
+ private static final long serialVersionUID = 1L;
/** Type used for all FunctionNodes */
public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
@@ -77,26 +86,41 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
CONSTANT_FOLDED,
/** method has been lowered */
LOWERED,
- /** method hass been attributed */
- ATTR,
+ /** program points have been assigned to unique locations */
+ PROGRAM_POINTS_ASSIGNED,
+ /** any transformations of builtins have taken place, e.g. apply=&gt;call */
+ BUILTINS_TRANSFORMED,
/** method has been split */
SPLIT,
- /** method has had its types finalized */
- FINALIZED,
+ /** method has had symbols assigned */
+ SYMBOLS_ASSIGNED,
+ /** computed scope depths for symbols */
+ SCOPE_DEPTHS_COMPUTED,
+ /** method has had types calculated*/
+ OPTIMISTIC_TYPES_ASSIGNED,
+ /** method has had types calculated */
+ LOCAL_VARIABLE_TYPES_CALCULATED,
+ /** compile units reused (optional) */
+ COMPILE_UNITS_REUSED,
/** method has been emitted to bytecode */
- EMITTED
+ BYTECODE_GENERATED,
+ /** method has been installed */
+ BYTECODE_INSTALLED
}
+
/** Source of entity. */
- private final Source source;
+ private transient final Source source;
+
+ /**
+ * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
+ * to skip parsing inner functions.
+ */
+ private final Object endParserState;
/** External function identifier. */
@Ignore
private final IdentNode ident;
- /** Parsed version of functionNode */
- @Ignore
- private final FunctionNode snapshot;
-
/** The body of the function node */
private final Block body;
@@ -118,32 +142,26 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Last token of function. **/
private final long lastToken;
- /** Declared symbols in this function node */
- @Ignore
- private final Set<Symbol> declaredSymbols;
-
/** Method's namespace. */
- private final Namespace namespace;
+ private transient final Namespace namespace;
/** Current compilation state */
@Ignore
private final EnumSet<CompilationState> compilationState;
+ /** Number of properties of "this" object assigned in this function */
@Ignore
- private final Compiler.Hints hints;
-
- /** Properties of this object assigned in this function */
- @Ignore
- private HashSet<String> thisProperties;
+ private final int thisProperties;
/** Function flags. */
private final int flags;
- /** //@ sourceURL or //# sourceURL for program function nodes */
- private final String sourceURL;
-
+ /** Line number of function start */
private final int lineNumber;
+ /** Root class for function */
+ private final Class<?> rootClass;
+
/** Is anonymous function flag. */
public static final int IS_ANONYMOUS = 1 << 0;
@@ -156,7 +174,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Does the function use the "arguments" identifier ? */
public static final int USES_ARGUMENTS = 1 << 3;
- /** Has this node been split because it was too large? */
+ /** Has this function been split because it was too large? */
public static final int IS_SPLIT = 1 << 4;
/** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
@@ -182,36 +200,87 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
public static final int USES_ANCESTOR_SCOPE = 1 << 9;
- /** Is this function lazily compiled? */
- public static final int IS_LAZY = 1 << 10;
+ /** Does this function have nested declarations? */
+ public static final int HAS_FUNCTION_DECLARATIONS = 1 << 10;
- /** Does this function have lazy, yet uncompiled children */
- public static final int HAS_LAZY_CHILDREN = 1 << 11;
+ /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
+ public static final int IS_DEOPTIMIZABLE = 1 << 11;
- /** Does this function have lazy, yet uncompiled children */
- public static final int IS_PROGRAM = 1 << 12;
+ /** Are we vararg, but do we just pass the arguments along to apply or call */
+ public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
- /** Does this function have nested declarations? */
- public static final int HAS_FUNCTION_DECLARATIONS = 1 << 13;
+ /**
+ * Is this function the top-level program?
+ */
+ public static final int IS_PROGRAM = 1 << 13;
- /** Can this function be specialized? */
- public static final int CAN_SPECIALIZE = 1 << 14;
+ /**
+ * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
+ * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
+ * use the symbol in their parent scope instead when they reference themselves by name.
+ */
+ public static final int USES_SELF_SYMBOL = 1 << 14;
/** Does this function use the "this" keyword? */
- public static final int USES_THIS = 1 << 15;
+ public static final int USES_THIS = 1 << 15;
+
+ /** Is this declared in a dynamic context */
+ public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
+
+ /**
+ * The following flags are derived from directive comments within this function.
+ * Note that even IS_STRICT is one such flag but that requires special handling.
+ */
+
+ /** parser, print parse tree */
+ public static final int IS_PRINT_PARSE = 1 << 17;
+ /** parser, print lower parse tree */
+ public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
+ /** parser, print AST */
+ public static final int IS_PRINT_AST = 1 << 19;
+ /** parser, print lower AST */
+ public static final int IS_PRINT_LOWER_AST = 1 << 20;
+ /** parser, print symbols */
+ public static final int IS_PRINT_SYMBOLS = 1 << 21;
+
+ // callsite tracing, profiling within this function
+ /** profile callsites in this function? */
+ public static final int IS_PROFILE = 1 << 22;
+
+ /** trace callsite enterexit in this function? */
+ public static final int IS_TRACE_ENTEREXIT = 1 << 23;
+
+ /** trace callsite misses in this function? */
+ public static final int IS_TRACE_MISSES = 1 << 24;
+
+ /** trace callsite values in this function? */
+ public static final int IS_TRACE_VALUES = 1 << 25;
+
+ /**
+ * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
+ * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
+ * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
+ * will, however, cache the value of this flag.
+ */
+ public static final int NEEDS_CALLEE = 1 << 26;
+
+ /** extension callsite flags mask */
+ public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
+ IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
+ IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
+ IS_TRACE_MISSES | IS_TRACE_VALUES;
/** Does this function or any nested functions contain an eval? */
private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
/** Does this function need to store all its variables in scope? */
- private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL | IS_SPLIT | HAS_LAZY_CHILDREN;
+ private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
/** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
- /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval.
- * We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */
- private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | HAS_LAZY_CHILDREN;
+ /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
+ public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
/** What is the return type of this function? */
private Type returnType = Type.UNKNOWN;
@@ -223,14 +292,13 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @param lineNumber line number
* @param token token
* @param finish finish
- * @param firstToken first token of the funtion node (including the function declaration)
+ * @param firstToken first token of the function node (including the function declaration)
* @param namespace the namespace
* @param ident the identifier
* @param name the name of the function
* @param parameters parameter list
* @param kind kind of function as in {@link FunctionNode.Kind}
* @param flags initial flags
- * @param sourceURL sourceURL specified in script (optional)
*/
public FunctionNode(
final Source source,
@@ -243,8 +311,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
final String name,
final List<IdentNode> parameters,
final FunctionNode.Kind kind,
- final int flags,
- final String sourceURL) {
+ final int flags) {
super(token, finish);
this.source = source;
@@ -257,32 +324,33 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this.lastToken = token;
this.namespace = namespace;
this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
- this.declaredSymbols = new HashSet<>();
this.flags = flags;
- this.sourceURL = sourceURL;
this.compileUnit = null;
this.body = null;
- this.snapshot = null;
- this.hints = null;
+ this.thisProperties = 0;
+ this.rootClass = null;
+ this.endParserState = null;
}
private FunctionNode(
final FunctionNode functionNode,
final long lastToken,
+ final Object endParserState,
final int flags,
- final String sourceURL,
final String name,
final Type returnType,
final CompileUnit compileUnit,
final EnumSet<CompilationState> compilationState,
final Block body,
final List<IdentNode> parameters,
- final FunctionNode snapshot,
- final Compiler.Hints hints) {
+ final int thisProperties,
+ final Class<?> rootClass,
+ final Source source, Namespace namespace) {
super(functionNode);
+
+ this.endParserState = endParserState;
this.lineNumber = functionNode.lineNumber;
this.flags = flags;
- this.sourceURL = sourceURL;
this.name = name;
this.returnType = returnType;
this.compileUnit = compileUnit;
@@ -290,17 +358,15 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this.compilationState = compilationState;
this.body = body;
this.parameters = parameters;
- this.snapshot = snapshot;
- this.hints = hints;
+ this.thisProperties = thisProperties;
+ this.rootClass = rootClass;
+ this.source = source;
+ this.namespace = namespace;
// the fields below never change - they are final and assigned in constructor
- this.source = functionNode.source;
this.ident = functionNode.ident;
- this.namespace = functionNode.namespace;
- this.declaredSymbols = functionNode.declaredSymbols;
this.kind = functionNode.kind;
this.firstToken = functionNode.firstToken;
- this.thisProperties = functionNode.thisProperties;
}
@Override
@@ -312,98 +378,156 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
- * Get the source for this function
- * @return the source
+ * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
+ * @param visitor the visitor to apply to the nodes.
+ * @return a list of parameter nodes, potentially modified from original ones by the visitor.
*/
- public Source getSource() {
- return source;
+ public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
+ return Node.accept(visitor, parameters);
}
/**
- * get source name - sourceURL or name derived from Source.
+ * Get additional callsite flags to be used specific to this function.
*
- * @return name for the script source
+ * @return callsite flags
*/
- public String getSourceName() {
- return (sourceURL != null)? sourceURL : source.getName();
+ public int getCallSiteFlags() {
+ int callsiteFlags = 0;
+ if (getFlag(IS_STRICT)) {
+ callsiteFlags |= CALLSITE_STRICT;
+ }
+
+ // quick check for extension callsite flags turned on by directives.
+ if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
+ return callsiteFlags;
+ }
+
+ if (getFlag(IS_PROFILE)) {
+ callsiteFlags |= CALLSITE_PROFILE;
+ }
+
+ if (getFlag(IS_TRACE_MISSES)) {
+ callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
+ }
+
+ if (getFlag(IS_TRACE_VALUES)) {
+ callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
+ }
+
+ if (getFlag(IS_TRACE_ENTEREXIT)) {
+ callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
+ }
+
+ return callsiteFlags;
}
/**
- * get the sourceURL
- * @return the sourceURL
+ * Get the source for this function
+ * @return the source
*/
- public String getSourceURL() {
- return sourceURL;
+ public Source getSource() {
+ return source;
}
/**
- * Set the sourceURL
- *
- * @param lc lexical context
- * @param newSourceURL source url string to set
- * @return function node or a new one if state was changed
+ * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
+ * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
+ * a deserialized function node.
+ * @param source the source for the function.
+ * @param namespace the namespace for the function
+ * @return a new function node with the set source and namespace
+ * @throws IllegalArgumentException if the specified source or namespace is null
+ * @throws IllegalStateException if the function already has either a source or namespace set.
*/
- public FunctionNode setSourceURL(final LexicalContext lc, final String newSourceURL) {
- if (Objects.equals(sourceURL, newSourceURL)) {
+ public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
+ if (source == null || namespace == null) {
+ throw new IllegalArgumentException();
+ } else if (this.source == source && this.namespace == namespace) {
return this;
+ } else if (this.source != null || this.namespace != null) {
+ throw new IllegalStateException();
}
-
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, newSourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ return new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace);
}
/**
- * Returns the line number.
- * @return the line number.
+ * Get the unique ID for this function within the script file.
+ * @return the id
*/
- public int getLineNumber() {
- return lineNumber;
+ public int getId() {
+ return position();
}
/**
- * Get the version of this function node's code as it looked upon construction
- * i.e typically parsed and nothing else
- * @return initial version of function node
+ * get source name - sourceURL or name derived from Source.
+ *
+ * @return name for the script source
*/
- public FunctionNode getSnapshot() {
- return snapshot;
+ public String getSourceName() {
+ return getSourceName(source);
}
/**
- * Throw away the snapshot, if any, to save memory. Used when heuristic
- * determines that a method is not worth specializing
+ * Static source name getter
*
- * @param lc lexical context
- * @return new function node if a snapshot was present, now with snapsnot null
+ * @param source the source
+ * @return source name
*/
- public FunctionNode clearSnapshot(final LexicalContext lc) {
- if (this.snapshot == null) {
- return this;
- }
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ public static String getSourceName(final Source source) {
+ final String explicitURL = source.getExplicitURL();
+ return explicitURL != null ? explicitURL : source.getName();
}
/**
- * Take a snapshot of this function node at a given point in time
- * and store it in the function node
- * @param lc lexical context
- * @return function node
+ * Function to parse nashorn per-function extension directive comments.
+ *
+ * @param directive nashorn extension directive string
+ * @return integer flag for the given directive.
*/
- public FunctionNode snapshot(final LexicalContext lc) {
- if (this.snapshot == this) {
- return this;
- }
- if (isProgram() || parameters.isEmpty()) {
- return this; //never specialize anything that won't be recompiled
+ public static int getDirectiveFlag(final String directive) {
+ switch (directive) {
+ case "nashorn callsite trace enterexit":
+ return IS_TRACE_ENTEREXIT;
+ case "nashorn callsite trace misses":
+ return IS_TRACE_MISSES;
+ case "nashorn callsite trace objects":
+ return IS_TRACE_VALUES;
+ case "nashorn callsite profile":
+ return IS_PROFILE;
+ case "nashorn print parse":
+ return IS_PRINT_PARSE;
+ case "nashorn print lower parse":
+ return IS_PRINT_LOWER_PARSE;
+ case "nashorn print ast":
+ return IS_PRINT_AST;
+ case "nashorn print lower ast":
+ return IS_PRINT_LOWER_AST;
+ case "nashorn print symbols":
+ return IS_PRINT_SYMBOLS;
+ default:
+ // unknown/unsupported directive
+ return 0;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
}
/**
- * Can this function node be regenerated with more specific type args?
- * @return true if specialization is possible
+ * Returns the line number.
+ * @return the line number.
*/
- public boolean canSpecialize() {
- return snapshot != null && getFlag(CAN_SPECIALIZE);
+ public int getLineNumber() {
+ return lineNumber;
}
/**
@@ -421,21 +545,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @return true of the node is in the given state
*/
public boolean hasState(final EnumSet<CompilationState> state) {
- return compilationState.equals(state);
- }
-
- /**
- * Check whether the state of this FunctionNode contains a given compilation
- * state.
- *
- * A node can be in many states at once, e.g. both lowered and initialized.
- * To check for an exact state, use {FunctionNode{@link #hasState(EnumSet)}
- *
- * @param state state to check for
- * @return true if state is present in the total compilation state of this FunctionNode
- */
- public boolean hasState(final CompilationState state) {
- return compilationState.contains(state);
+ return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
}
/**
@@ -448,35 +558,52 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @return function node or a new one if state was changed
*/
public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
- if (this.compilationState.contains(state)) {
+ if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
return this;
}
final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
newState.add(state);
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
- }
-
- /**
- * Get any compiler hints that may associated with the function
- * @return compiler hints
- */
- public Compiler.Hints getHints() {
- return this.hints == null ? Compiler.Hints.EMPTY : hints;
+ return setCompilationState(lc, newState);
}
/**
- * Set compiler hints for this function
- * @param lc lexical context
- * @param hints compiler hints
- * @return new function if hints changed
+ * Copy a compilation state from an original function to this function. Used when creating synthetic
+ * function nodes by the splitter.
+ *
+ * @param lc lexical context
+ * @param original the original function node to copy compilation state from
+ * @return function node or a new one if state was changed
*/
- public FunctionNode setHints(final LexicalContext lc, final Compiler.Hints hints) {
- if (this.hints == hints) {
+ public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
+ final EnumSet<CompilationState> origState = original.compilationState;
+ if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
+ newState.addAll(origState);
+ return setCompilationState(lc, newState);
}
+ private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
+ }
+
+
/**
* Create a unique name in the namespace of this FunctionNode
* @param base prefix for name
@@ -486,48 +613,67 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return namespace.uniqueName(base);
}
-
@Override
- public void toString(final StringBuilder sb) {
- sb.append('[');
- sb.append(returnType);
- sb.append(']');
- sb.append(' ');
+ public void toString(final StringBuilder sb, final boolean printTypes) {
+ sb.append('[').
+ append(returnType).
+ append(']').
+ append(' ');
sb.append("function");
if (ident != null) {
sb.append(' ');
- ident.toString(sb);
+ ident.toString(sb, printTypes);
}
sb.append('(');
- boolean first = true;
- for (final IdentNode parameter : parameters) {
- if (!first) {
+ for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
+ final IdentNode parameter = iter.next();
+ if (parameter.getSymbol() != null) {
+ sb.append('[').append(parameter.getType()).append(']').append(' ');
+ }
+ parameter.toString(sb, printTypes);
+ if (iter.hasNext()) {
sb.append(", ");
- } else {
- first = false;
}
-
- parameter.toString(sb);
}
sb.append(')');
}
@Override
+ public int getFlags() {
+ return flags;
+ }
+
+ @Override
public boolean getFlag(final int flag) {
return (flags & flag) != 0;
}
@Override
- public FunctionNode setFlags(final LexicalContext lc, int flags) {
+ public FunctionNode setFlags(final LexicalContext lc, final int flags) {
if (this.flags == flags) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
}
@Override
@@ -549,23 +695,32 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
- * Should this function node be lazily code generated, i.e. first at link time
- * @return true if lazy
+ * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
+ * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
*/
- public boolean isLazy() {
- return getFlag(IS_LAZY);
+ public boolean canBeDeoptimized() {
+ return getFlag(IS_DEOPTIMIZABLE);
}
/**
- * Check if the {@code eval} keyword is used in this function
+ * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
*
- * @return true if {@code eval} is used
+ * @return true if {@code eval} is called.
*/
public boolean hasEval() {
return getFlag(HAS_EVAL);
}
/**
+ * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
+ *
+ * @return true if a nested function calls {@code eval}.
+ */
+ public boolean hasNestedEval() {
+ return getFlag(HAS_NESTED_EVAL);
+ }
+
+ /**
* Get the first token for this function
* @return the first token
*/
@@ -587,10 +742,14 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
* for split functions to make sure symbols slots are the same in the main and split methods.
*
+ * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
+ * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
+ *
* @return true if the function's generated Java method needs a {@code callee} parameter.
*/
public boolean needsCallee() {
- return needsParentScope() || needsSelfSymbol() || isSplit() || (needsArguments() && !isStrict());
+ // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
+ return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
}
/**
@@ -602,30 +761,21 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return getFlag(USES_THIS);
}
- /**
- * Get the identifier for this function, this is its symbol.
- * @return the identifier as an IdentityNode
- */
- public IdentNode getIdent() {
- return ident;
- }
/**
- * Return a set of symbols declared in this function node. This
- * is only relevant after Attr, otherwise it will be an empty
- * set as no symbols have been introduced
- * @return set of declared symbols in function
+ * Return true if function contains an apply to call transform
+ * @return true if this function has transformed apply to call
*/
- public Set<Symbol> getDeclaredSymbols() {
- return Collections.unmodifiableSet(declaredSymbols);
+ public boolean hasOptimisticApplyToCall() {
+ return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
}
/**
- * Add a declared symbol to this function node
- * @param symbol symbol that is declared
+ * Get the identifier for this function, this is its symbol.
+ * @return the identifier as an IdentityNode
*/
- public void addDeclaredSymbol(final Symbol symbol) {
- declaredSymbols.add(symbol);
+ public IdentNode getIdent() {
+ return ident;
}
/**
@@ -643,10 +793,28 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @return new function node if body changed, same if not
*/
public FunctionNode setBody(final LexicalContext lc, final Block body) {
- if(this.body == body) {
+ if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags |
+ (body.needsScope() ?
+ FunctionNode.HAS_SCOPE_BLOCK :
+ 0),
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
}
/**
@@ -662,6 +830,36 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
+ * Was this function declared in a dynamic context, i.e. in a with or eval style
+ * chain
+ * @return true if in dynamic context
+ */
+ public boolean inDynamicContext() {
+ return getFlag(IN_DYNAMIC_CONTEXT);
+ }
+
+ /**
+ * Check whether a function would need dynamic scope, which is does if it has
+ * evals and isn't strict.
+ * @return true if dynamic scope is needed
+ */
+ public boolean needsDynamicScope() {
+ // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
+ // variable into the function's scope), and it isn't strict (as evals in strict functions get an
+ // isolated scope).
+ return hasEval() && !isStrict();
+ }
+
+ /**
+ * Flag this function as declared in a dynamic context
+ * @param lc lexical context
+ * @return new function node, or same if unmodified
+ */
+ public FunctionNode setInDynamicContext(final LexicalContext lc) {
+ return setFlag(lc, IN_DYNAMIC_CONTEXT);
+ }
+
+ /**
* Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
* Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
* (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
@@ -684,26 +882,43 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @return true if the function needs parent scope.
*/
public boolean needsParentScope() {
- return getFlag(NEEDS_PARENT_SCOPE) || isProgram();
+ return getFlag(NEEDS_PARENT_SCOPE);
}
/**
- * Register a property assigned to the this object in this function.
- * @param key the property name
+ * Set the number of properties assigned to the this object in this function.
+ * @param lc the current lexical context.
+ * @param thisProperties number of properties
+ * @return a potentially modified function node
*/
- public void addThisProperty(final String key) {
- if (thisProperties == null) {
- thisProperties = new HashSet<>();
+ public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
+ if (this.thisProperties == thisProperties) {
+ return this;
}
- thisProperties.add(key);
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
}
/**
* Get the number of properties assigned to the this object in this function.
* @return number of properties
*/
- public int countThisProperties() {
- return thisProperties == null ? 0 : thisProperties.size();
+ public int getThisProperties() {
+ return thisProperties;
}
/**
@@ -741,7 +956,60 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.lastToken == lastToken) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
+ }
+
+ /**
+ * Returns the end parser state for this function.
+ * @return the end parser state for this function.
+ */
+ public Object getEndParserState() {
+ return endParserState;
+ }
+
+ /**
+ * Set the end parser state for this function.
+ * @param lc lexical context
+ * @param endParserState the parser state to set
+ * @return function node or a new one if state was changed
+ */
+ public FunctionNode setEndParserState(final LexicalContext lc, final Object endParserState) {
+ if (this.endParserState == endParserState) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass,
+ source,
+ namespace));
}
/**
@@ -752,7 +1020,6 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return name;
}
-
/**
* Set the internal name for this function
* @param lc lexical context
@@ -763,38 +1030,46 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.name.equals(name)) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass,
+ source,
+ namespace));
}
/**
- * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and
+ * Check if this function should have all its variables in its own scope. Split sub-functions, and
* functions having with and/or eval blocks are such.
*
* @return true if all variables should be in scope
*/
public boolean allVarsInScope() {
- return isProgram() || getFlag(HAS_ALL_VARS_IN_SCOPE);
+ return getFlag(HAS_ALL_VARS_IN_SCOPE);
}
/**
- * Checks if this function is a sub-function generated by splitting a larger one
+ * Checks if this function is split into several smaller fragments.
*
- * @return true if this function is split from a larger one
+ * @return true if this function is split into several smaller fragments.
*/
public boolean isSplit() {
return getFlag(IS_SPLIT);
}
/**
- * Checks if this function has yet-to-be-generated child functions
- *
- * @return true if there are lazy child functions
- */
- public boolean hasLazyChildren() {
- return getFlag(HAS_LAZY_CHILDREN);
- }
-
- /**
* Get the parameters to this function
* @return a list of IdentNodes which represent the function parameters, in order
*/
@@ -803,6 +1078,16 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
+ * Returns the identifier for a named parameter at the specified position in this function's parameter list.
+ * @param index the parameter's position.
+ * @return the identifier for the requested named parameter.
+ * @throws IndexOutOfBoundsException if the index is invalid.
+ */
+ public IdentNode getParameter(final int index) {
+ return parameters.get(index);
+ }
+
+ /**
* Reset the compile unit used to compile this function
* @see Compiler
* @param lc lexical context
@@ -813,7 +1098,22 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.parameters == parameters) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
}
/**
@@ -833,16 +1133,22 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
- * Does this function need a self symbol - this is needed only for self
- * referring functions
- * @return true if function needs a symbol for self
+ * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
+ * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
+ * scope (since they're bound to the symbol with their name in their enclosing scope).
+ * @return true if this function node is a named function expression that uses the symbol for itself.
*/
- public boolean needsSelfSymbol() {
- return body.getFlag(Block.NEEDS_SELF_SYMBOL);
+ public boolean usesSelfSymbol() {
+ return getFlag(USES_SELF_SYMBOL);
+ }
+
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return FUNCTION_TYPE;
}
@Override
- public Type getType() {
+ public Type getWidestOperationType() {
return FUNCTION_TYPE;
}
@@ -867,27 +1173,28 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
//we never bother with object types narrower than objects, that will lead to byte code verification errors
//as for instance even if we know we are returning a string from a method, the code generator will always
//treat it as an object, at least for now
- if (this.returnType == returnType) {
+ final Type type = returnType.isObject() ? Type.OBJECT : returnType;
+ if (this.returnType == type) {
return this;
}
- final Type type = Type.widest(this.returnType, returnType.isObject() ? Type.OBJECT : returnType);
return Node.replaceInLexicalContext(
lc,
this,
new FunctionNode(
this,
lastToken,
+ endParserState,
flags,
- sourceURL,
name,
type,
compileUnit,
compilationState,
- body.setReturnType(type),
+ body,
parameters,
- snapshot,
- hints));
- }
+ thisProperties,
+ rootClass, source, namespace
+ ));
+ }
/**
* Check if the function is generated in strict mode
@@ -902,6 +1209,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @see Compiler
* @return the compile unit
*/
+ @Override
public CompileUnit getCompileUnit() {
return compileUnit;
}
@@ -917,7 +1225,22 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.compileUnit == compileUnit) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
}
/**
@@ -938,4 +1261,41 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
public Symbol compilerConstant(final CompilerConstants cc) {
return body.getExistingSymbol(cc.symbolName());
}
+
+ /**
+ * Get the root class that this function node compiles to
+ * @return root class
+ */
+ public Class<?> getRootClass() {
+ return rootClass;
+ }
+
+ /**
+ * Reset the root class that this function is compiled to
+ * @see Compiler
+ * @param lc lexical context
+ * @param rootClass root class
+ * @return function node or a new one if state was changed
+ */
+ public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
+ if (this.rootClass == rootClass) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(
+ lc,
+ this,
+ new FunctionNode(
+ this,
+ lastToken,
+ endParserState,
+ flags,
+ name,
+ returnType,
+ compileUnit,
+ compilationState,
+ body,
+ parameters,
+ thisProperties,
+ rootClass, source, namespace));
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/GetSplitState.java b/src/jdk/nashorn/internal/ir/GetSplitState.java
new file mode 100644
index 00000000..bf4a4c01
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/GetSplitState.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Scope;
+
+/**
+ * Synthetic AST node that represents loading of the scope object and invocation of the {@link Scope#getSplitState()}
+ * method on it. It has no JavaScript source representation and only occurs in synthetic functions created by
+ * the split-into-functions transformation.
+ */
+public final class GetSplitState extends Expression {
+ private static final long serialVersionUID = 1L;
+
+ /** The sole instance of this AST node. */
+ public final static GetSplitState INSTANCE = new GetSplitState();
+
+ private GetSplitState() {
+ super(NO_TOKEN, NO_FINISH);
+ }
+
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return Type.INT;
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ return visitor.enterGetSplitState(this) ? visitor.leaveGetSplitState(this) : this;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ if (printType) {
+ sb.append("{I}");
+ }
+ sb.append(CompilerConstants.SCOPE.symbolName()).append('.').append(Scope.GET_SPLIT_STATE.name()).append("()");
+ }
+
+ private Object readResolve() {
+ return INSTANCE;
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/IdentNode.java b/src/jdk/nashorn/internal/ir/IdentNode.java
index 30e8ed11..7059734d 100644
--- a/src/jdk/nashorn/internal/ir/IdentNode.java
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java
@@ -28,29 +28,44 @@ package jdk.nashorn.internal.ir;
import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
/**
* IR representation for an identifier.
*/
@Immutable
-public final class IdentNode extends Expression implements PropertyKey, FunctionCall {
+public final class IdentNode extends Expression implements PropertyKey, FunctionCall, Optimistic, JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
private static final int PROPERTY_NAME = 1 << 0;
private static final int INITIALIZED_HERE = 1 << 1;
private static final int FUNCTION = 1 << 2;
private static final int FUTURESTRICT_NAME = 1 << 3;
+ private static final int IS_DECLARED_HERE = 1 << 4;
+ private static final int IS_DEAD = 1 << 5;
/** Identifier. */
private final String name;
- /** Type for a callsite, e.g. X in a get()X or a set(X)V */
- private final Type callSiteType;
+ /** Optimistic type */
+ private final Type type;
private final int flags;
+ private final int programPoint;
+
+ private final LocalVariableConversion conversion;
+
+ private Symbol symbol;
+
+
/**
* Constructor
*
@@ -60,16 +75,21 @@ public final class IdentNode extends Expression implements PropertyKey, Function
*/
public IdentNode(final long token, final int finish, final String name) {
super(token, finish);
- this.name = name.intern();
- this.callSiteType = null;
+ this.name = name;
+ this.type = null;
this.flags = 0;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.conversion = null;
}
- private IdentNode(final IdentNode identNode, final String name, final Type callSiteType, final int flags) {
+ private IdentNode(final IdentNode identNode, final String name, final Type type, final int flags, final int programPoint, final LocalVariableConversion conversion) {
super(identNode);
this.name = name;
- this.callSiteType = callSiteType;
+ this.type = type;
this.flags = flags;
+ this.programPoint = programPoint;
+ this.conversion = conversion;
+ this.symbol = identNode.symbol;
}
/**
@@ -79,24 +99,33 @@ public final class IdentNode extends Expression implements PropertyKey, Function
*/
public IdentNode(final IdentNode identNode) {
super(identNode);
- this.name = identNode.getName();
- this.callSiteType = null;
- this.flags = identNode.flags;
+ this.name = identNode.getName();
+ this.type = identNode.type;
+ this.flags = identNode.flags;
+ this.conversion = identNode.conversion;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.symbol = identNode.symbol;
}
- @Override
- public Type getType() {
- return callSiteType == null ? super.getType() : callSiteType;
+ /**
+ * Creates an identifier for the symbol. Normally used by code generator for creating temporary storage identifiers
+ * that must contain both a symbol and a type.
+ * @param symbol the symbol to create a temporary identifier for.
+ * @return a temporary identifier for the symbol.
+ */
+ public static IdentNode createInternalIdentifier(final Symbol symbol) {
+ return new IdentNode(Token.toDesc(TokenType.IDENT, 0, 0), 0, symbol.getName()).setSymbol(symbol);
}
@Override
- public boolean isAtom() {
- return true;
- }
-
- private boolean hasCallSiteType() {
- //this is an identity that's part of a getter or setter
- return callSiteType != null;
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ if(type != null) {
+ return type;
+ } else if(symbol != null && symbol.isScope()) {
+ return Type.OBJECT;
+ }
+ final Type symbolType = localVariableTypes.apply(symbol);
+ return symbolType == null ? Type.UNDEFINED : symbolType;
}
/**
@@ -114,14 +143,10 @@ public final class IdentNode extends Expression implements PropertyKey, Function
}
@Override
- public void toString(final StringBuilder sb) {
- if (hasCallSiteType()) {
- sb.append('{');
- final String desc = getType().getDescriptor();
- sb.append(desc.charAt(desc.length() - 1) == ';' ? 'O' : getType().getDescriptor());
- sb.append('}');
+ public void toString(final StringBuilder sb, final boolean printType) {
+ if (printType) {
+ optimisticTypeToString(sb, symbol == null || !symbol.hasSlot());
}
-
sb.append(name);
}
@@ -144,11 +169,36 @@ public final class IdentNode extends Expression implements PropertyKey, Function
}
/**
+ * Return the Symbol the compiler has assigned to this identifier. The symbol is a description of the storage
+ * location for the identifier.
+ *
+ * @return the symbol
+ */
+ public Symbol getSymbol() {
+ return symbol;
+ }
+
+ /**
+ * Assign a symbol to this identifier. See {@link IdentNode#getSymbol()} for explanation of what a symbol is.
+ *
+ * @param symbol the symbol
+ * @return new node
+ */
+ public IdentNode setSymbol(final Symbol symbol) {
+ if (this.symbol == symbol) {
+ return this;
+ }
+ final IdentNode newIdent = (IdentNode)clone();
+ newIdent.symbol = symbol;
+ return newIdent;
+ }
+
+ /**
* Check if this IdentNode is a property name
* @return true if this is a property name
*/
public boolean isPropertyName() {
- return (flags & PROPERTY_NAME) != 0;
+ return (flags & PROPERTY_NAME) == PROPERTY_NAME;
}
/**
@@ -159,7 +209,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isPropertyName()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | PROPERTY_NAME);
+ return new IdentNode(this, name, type, flags | PROPERTY_NAME, programPoint, conversion);
}
/**
@@ -167,7 +217,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
* @return true if this is a future strict name
*/
public boolean isFutureStrictName() {
- return (flags & FUTURESTRICT_NAME) != 0;
+ return (flags & FUTURESTRICT_NAME) == FUTURESTRICT_NAME;
}
/**
@@ -178,7 +228,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isFutureStrictName()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | FUTURESTRICT_NAME);
+ return new IdentNode(this, name, type, flags | FUTURESTRICT_NAME, programPoint, conversion);
}
/**
@@ -186,7 +236,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
* @return true if IdentNode is initialized on creation
*/
public boolean isInitializedHere() {
- return (flags & INITIALIZED_HERE) != 0;
+ return (flags & INITIALIZED_HERE) == INITIALIZED_HERE;
}
/**
@@ -197,22 +247,69 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isInitializedHere()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | INITIALIZED_HERE);
+ return new IdentNode(this, name, type, flags | INITIALIZED_HERE, programPoint, conversion);
+ }
+
+ /**
+ * Is this a LET or CONST identifier used before its declaration?
+ *
+ * @return true if identifier is dead
+ */
+ public boolean isDead() {
+ return (flags & IS_DEAD) != 0;
+ }
+
+ /**
+ * Flag this IdentNode as a LET or CONST identifier used before its declaration.
+ *
+ * @return a new IdentNode equivalent to this but marked as dead.
+ */
+ public IdentNode markDead() {
+ return new IdentNode(this, name, type, flags | IS_DEAD, programPoint, conversion);
}
/**
- * Check if this IdentNode is a special identity, currently __DIR__, __FILE__
- * or __LINE__
+ * Is this IdentNode declared here?
*
- * @return true if this IdentNode is special
+ * @return true if identifier is declared here
*/
- public boolean isSpecialIdentity() {
+ public boolean isDeclaredHere() {
+ return (flags & IS_DECLARED_HERE) != 0;
+ }
+
+ /**
+ * Flag this IdentNode as being declared here.
+ *
+ * @return a new IdentNode equivalent to this but marked as declared here.
+ */
+ public IdentNode setIsDeclaredHere() {
+ if (isDeclaredHere()) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags | IS_DECLARED_HERE, programPoint, conversion);
+ }
+
+ /**
+ * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and
+ * __LINE__).
+ *
+ * @return true if this IdentNode's name is same as that of a compile-time property
+ */
+ public boolean isCompileTimePropertyName() {
return name.equals(__DIR__.symbolName()) || name.equals(__FILE__.symbolName()) || name.equals(__LINE__.symbolName());
}
@Override
public boolean isFunction() {
- return (flags & FUNCTION) != 0;
+ return (flags & FUNCTION) == FUNCTION;
+ }
+
+ @Override
+ public IdentNode setType(final Type type) {
+ if (this.type == type) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
}
/**
@@ -223,6 +320,68 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isFunction()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | FUNCTION);
+ return new IdentNode(this, name, type, flags | FUNCTION, programPoint, conversion);
+ }
+
+ /**
+ * Mark this node as not being the callee operand of a {@link CallNode}.
+ * @return an ident node identical to this one in all aspects except with its function flag unset.
+ */
+ public IdentNode setIsNotFunction() {
+ if (! isFunction()) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags & ~FUNCTION, programPoint, conversion);
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ @Override
+ public Optimistic setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ return Type.INT;
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return true;
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
+ }
+
+ /**
+ * Is this an internal symbol, i.e. one that starts with ':'. Those can
+ * never be optimistic.
+ * @return true if internal symbol
+ */
+ public boolean isInternal() {
+ assert name != null;
+ return name.charAt(0) == ':';
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
}
diff --git a/src/jdk/nashorn/internal/ir/IfNode.java b/src/jdk/nashorn/internal/ir/IfNode.java
index 64e70d87..cdebaad9 100644
--- a/src/jdk/nashorn/internal/ir/IfNode.java
+++ b/src/jdk/nashorn/internal/ir/IfNode.java
@@ -32,7 +32,9 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation for an IF statement.
*/
@Immutable
-public final class IfNode extends Statement {
+public final class IfNode extends Statement implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
/** Test expression. */
private final Expression test;
@@ -43,6 +45,12 @@ public final class IfNode extends Statement {
private final Block fail;
/**
+ * Local variable conversions that need to be performed after test if it evaluates to false, and there's no else
+ * branch.
+ */
+ private final LocalVariableConversion conversion;
+
+ /**
* Constructor
*
* @param lineNumber line number
@@ -57,13 +65,15 @@ public final class IfNode extends Statement {
this.test = test;
this.pass = pass;
this.fail = fail;
+ this.conversion = null;
}
- private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail) {
+ private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail, final LocalVariableConversion conversion) {
super(ifNode);
this.test = test;
this.pass = pass;
this.fail = fail;
+ this.conversion = conversion;
}
@Override
@@ -84,9 +94,9 @@ public final class IfNode extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printTypes) {
sb.append("if (");
- test.toString(sb);
+ test.toString(sb, printTypes);
sb.append(')');
}
@@ -102,7 +112,7 @@ public final class IfNode extends Statement {
if (this.fail == fail) {
return this;
}
- return new IfNode(this, test, pass, fail);
+ return new IfNode(this, test, pass, fail, conversion);
}
/**
@@ -117,7 +127,7 @@ public final class IfNode extends Statement {
if (this.pass == pass) {
return this;
}
- return new IfNode(this, test, pass, fail);
+ return new IfNode(this, test, pass, fail, conversion);
}
/**
@@ -137,6 +147,19 @@ public final class IfNode extends Statement {
if (this.test == test) {
return this;
}
- return new IfNode(this, test, pass, fail);
+ return new IfNode(this, test, pass, fail, conversion);
+ }
+
+ @Override
+ public IfNode setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new IfNode(this, test, pass, fail, conversion);
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
}
diff --git a/src/jdk/nashorn/internal/ir/IndexNode.java b/src/jdk/nashorn/internal/ir/IndexNode.java
index 83f58ffc..72df1f96 100644
--- a/src/jdk/nashorn/internal/ir/IndexNode.java
+++ b/src/jdk/nashorn/internal/ir/IndexNode.java
@@ -25,14 +25,16 @@
package jdk.nashorn.internal.ir;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-
/**
* IR representation of an indexed access (brackets operator.)
*/
@Immutable
public final class IndexNode extends BaseNode {
+ private static final long serialVersionUID = 1L;
+
/** Property index. */
private final Expression index;
@@ -49,8 +51,8 @@ public final class IndexNode extends BaseNode {
this.index = index;
}
- private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction) {
- super(indexNode, base, isFunction);
+ private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) {
+ super(indexNode, base, isFunction, type, programPoint);
this.index = index;
}
@@ -65,21 +67,25 @@ public final class IndexNode extends BaseNode {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
final boolean needsParen = tokenType().needsParens(base.tokenType(), true);
if (needsParen) {
sb.append('(');
}
- base.toString(sb);
+ if (printType) {
+ optimisticTypeToString(sb);
+ }
+
+ base.toString(sb, printType);
if (needsParen) {
sb.append(')');
}
sb.append('[');
- index.toString(sb);
+ index.toString(sb, printType);
sb.append(']');
}
@@ -95,7 +101,7 @@ public final class IndexNode extends BaseNode {
if (this.base == base) {
return this;
}
- return new IndexNode(this, base, index, isFunction());
+ return new IndexNode(this, base, index, isFunction(), type, programPoint);
}
/**
@@ -103,19 +109,34 @@ public final class IndexNode extends BaseNode {
* @param index new index expression
* @return a node equivalent to this one except for the requested change.
*/
- public IndexNode setIndex(Expression index) {
+ public IndexNode setIndex(final Expression index) {
if(this.index == index) {
return this;
}
- return new IndexNode(this, base, index, isFunction());
+ return new IndexNode(this, base, index, isFunction(), type, programPoint);
}
@Override
- public BaseNode setIsFunction() {
+ public IndexNode setType(final Type type) {
+ if (this.type == type) {
+ return this;
+ }
+ return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ }
+
+ @Override
+ public IndexNode setIsFunction() {
if (isFunction()) {
return this;
}
- return new IndexNode(this, base, index, true);
+ return new IndexNode(this, base, index, true, type, programPoint);
}
+ @Override
+ public IndexNode setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new IndexNode(this, base, index, isFunction(), type, programPoint);
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/JoinPredecessor.java b/src/jdk/nashorn/internal/ir/JoinPredecessor.java
new file mode 100644
index 00000000..e55aec09
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/JoinPredecessor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+/**
+ * Interface implemented by AST nodes that either can occur as predecessors of a control flow join, or contain a control
+ * flow join themselves. JoinPredecessor only provides a getter and setter for a {@link LocalVariableConversion}; the
+ * semantics of control flow for a particular node implementing the interface are shared between
+ * {@code LocalVariableTypesCalculator} that creates the conversions, and {@code CodeGenerator} that uses them.
+ */
+public interface JoinPredecessor {
+ /**
+ * Set the local variable conversions needed to unify their types at a control flow join point.
+ * @param lc the current lexical context
+ * @param conversion the conversions.
+ * @return this node or a different node representing the change.
+ */
+ public JoinPredecessor setLocalVariableConversion(LexicalContext lc, LocalVariableConversion conversion);
+
+ /**
+ * Returns the local variable conversions needed to unify their types at a control flow join point.
+ * @return the local variable conversions needed to unify their types at a control flow join point. Can be null.
+ * Can contain {@link LocalVariableConversion#isLive() dead conversions}.
+ */
+ public LocalVariableConversion getLocalVariableConversion();
+}
diff --git a/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java b/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
new file mode 100644
index 00000000..cfb0086b
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * A wrapper for an expression that is in a position to be a join predecessor.
+ */
+public class JoinPredecessorExpression extends Expression implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
+ private final Expression expression;
+ private final LocalVariableConversion conversion;
+
+ /**
+ * A no-arg constructor does not wrap any expression on its own, but can be used as a place to contain a local
+ * variable conversion in a place where an expression can otherwise stand.
+ */
+ public JoinPredecessorExpression() {
+ this(null);
+ }
+
+ /**
+ * A constructor for wrapping an expression and making it a join predecessor. Typically used on true and false
+ * subexpressions of the ternary node as well as on the operands of short-circuiting logical expressions {@code &&}
+ * and {@code ||}.
+ * @param expression the expression to wrap
+ */
+ public JoinPredecessorExpression(final Expression expression) {
+ this(expression, null);
+ }
+
+ private JoinPredecessorExpression(final Expression expression, final LocalVariableConversion conversion) {
+ super(expression == null ? 0L : expression.getToken(), expression == null ? 0 : expression.getStart(), expression == null ? 0 : expression.getFinish());
+ this.expression = expression;
+ this.conversion = conversion;
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(conversion == this.conversion) {
+ return this;
+ }
+ return new JoinPredecessorExpression(expression, conversion);
+ }
+
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return expression.getType(localVariableTypes);
+ }
+
+ @Override
+ public boolean isAlwaysFalse() {
+ return expression != null && expression.isAlwaysFalse();
+ }
+
+ @Override
+ public boolean isAlwaysTrue() {
+ return expression != null && expression.isAlwaysTrue();
+ }
+
+ /**
+ * Returns the underlying expression.
+ * @return the underlying expression.
+ */
+ public Expression getExpression() {
+ return expression;
+ }
+
+ /**
+ * Sets the underlying expression.
+ * @param expression the new underlying expression
+ * @return this or modified join predecessor expression object.
+ */
+ public JoinPredecessorExpression setExpression(final Expression expression) {
+ if(expression == this.expression) {
+ return this;
+ }
+ return new JoinPredecessorExpression(expression, conversion);
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ if(visitor.enterJoinPredecessorExpression(this)) {
+ final Expression expr = getExpression();
+ return visitor.leaveJoinPredecessorExpression(expr == null ? this : setExpression((Expression)expr.accept(visitor)));
+ }
+ return this;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ if(expression != null) {
+ expression.toString(sb, printType);
+ }
+ if(conversion != null) {
+ conversion.toString(sb);
+ }
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/ir/JumpStatement.java b/src/jdk/nashorn/internal/ir/JumpStatement.java
new file mode 100644
index 00000000..07707171
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/JumpStatement.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.Label;
+
+/**
+ * Common base class for jump statements (e.g. {@code break} and {@code continue}).
+ */
+public abstract class JumpStatement extends Statement implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
+ private final String labelName;
+ private final LocalVariableConversion conversion;
+
+ /**
+ * Constructor
+ *
+ * @param lineNumber line number
+ * @param token token
+ * @param finish finish
+ * @param labelName label name for break or null if none
+ */
+ protected JumpStatement(final int lineNumber, final long token, final int finish, final String labelName) {
+ super(lineNumber, token, finish);
+ this.labelName = labelName;
+ this.conversion = null;
+ }
+
+ /**
+ * Copy constructor.
+ * @param jumpStatement the original jump statement.
+ * @param conversion a new local variable conversion.
+ */
+ protected JumpStatement(final JumpStatement jumpStatement, final LocalVariableConversion conversion) {
+ super(jumpStatement);
+ this.labelName = jumpStatement.labelName;
+ this.conversion = conversion;
+ }
+
+ @Override
+ public boolean hasGoto() {
+ return true;
+ }
+
+ /**
+ * Get the label name for this break node
+ * @return label name, or null if none
+ */
+ public String getLabelName() {
+ return labelName;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ sb.append(getStatementName());
+
+ if (labelName != null) {
+ sb.append(' ').append(labelName);
+ }
+ }
+
+ abstract String getStatementName();
+
+ /**
+ * Finds the target for this jump statement in a lexical context.
+ * @param lc the lexical context
+ * @return the target, or null if not found
+ */
+ public abstract BreakableNode getTarget(final LexicalContext lc);
+
+ /**
+ * Returns the label corresponding to this kind of jump statement (either a break or continue label) in the target.
+ * @param target the target. Note that it need not be the target of this jump statement, as the method can retrieve
+ * a label on any passed target as long as the target has a label of the requisite kind. Of course, it is advisable
+ * to invoke the method on a jump statement that targets the breakable.
+ * @return the label of the target corresponding to the kind of jump statement.
+ * @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to
+ * handle.
+ */
+ public abstract Label getTargetLabel(final BreakableNode target);
+
+ @Override
+ public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return createNewJumpStatement(conversion);
+ }
+
+ abstract JumpStatement createNewJumpStatement(LocalVariableConversion newConversion);
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/LabelNode.java b/src/jdk/nashorn/internal/ir/LabelNode.java
index 9903c2b0..744ba54b 100644
--- a/src/jdk/nashorn/internal/ir/LabelNode.java
+++ b/src/jdk/nashorn/internal/ir/LabelNode.java
@@ -29,36 +29,44 @@ import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
/**
- * IR representation for a labeled statement.
+ * IR representation for a labeled statement. It implements JoinPredecessor to hold conversions that need to be effected
+ * when the block exits normally, but is also targeted by a break statement that might bring different local variable
+ * types to the join at the break point.
*/
@Immutable
-public final class LabelNode extends LexicalContextStatement {
+public final class LabelNode extends LexicalContextStatement implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
/** Label ident. */
- private final IdentNode label;
+ private final String labelName;
/** Statements. */
private final Block body;
+ private final LocalVariableConversion localVariableConversion;
+
/**
* Constructor
*
* @param lineNumber line number
* @param token token
* @param finish finish
- * @param label label identifier
+ * @param labelName label name
* @param body body of label node
*/
- public LabelNode(final int lineNumber, final long token, final int finish, final IdentNode label, final Block body) {
+ public LabelNode(final int lineNumber, final long token, final int finish, final String labelName, final Block body) {
super(lineNumber, token, finish);
- this.label = label;
+ this.labelName = labelName;
this.body = body;
+ this.localVariableConversion = null;
}
- private LabelNode(final LabelNode labelNode, final IdentNode label, final Block body) {
+ private LabelNode(final LabelNode labelNode, final String labelName, final Block body, final LocalVariableConversion localVariableConversion) {
super(labelNode);
- this.label = label;
- this.body = body;
+ this.labelName = labelName;
+ this.body = body;
+ this.localVariableConversion = localVariableConversion;
}
@Override
@@ -69,18 +77,15 @@ public final class LabelNode extends LexicalContextStatement {
@Override
public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLabelNode(this)) {
- return visitor.leaveLabelNode(
- setLabel(lc, (IdentNode)label.accept(visitor)).
- setBody(lc, (Block)body.accept(visitor)));
+ return visitor.leaveLabelNode(setBody(lc, (Block)body.accept(visitor)));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
- label.toString(sb);
- sb.append(':');
+ public void toString(final StringBuilder sb, final boolean printType) {
+ sb.append(labelName).append(':');
}
/**
@@ -101,22 +106,27 @@ public final class LabelNode extends LexicalContextStatement {
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new LabelNode(this, label, body));
+ return Node.replaceInLexicalContext(lc, this, new LabelNode(this, labelName, body, localVariableConversion));
}
/**
- * Get the identifier representing the label name
+ * Get the label name
* @return the label
*/
- public IdentNode getLabel() {
- return label;
+ public String getLabelName() {
+ return labelName;
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return localVariableConversion;
}
- private LabelNode setLabel(final LexicalContext lc, final IdentNode label) {
- if (this.label == label) {
+ @Override
+ public LabelNode setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion localVariableConversion) {
+ if(this.localVariableConversion == localVariableConversion) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new LabelNode(this, label, body));
+ return Node.replaceInLexicalContext(lc, this, new LabelNode(this, labelName, body, localVariableConversion));
}
-
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java b/src/jdk/nashorn/internal/ir/Labels.java
index f2089d5a..ce5e9dc4 100644
--- a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
+++ b/src/jdk/nashorn/internal/ir/Labels.java
@@ -23,29 +23,21 @@
* questions.
*/
-package jdk.nashorn.internal.runtime.linker;
+package jdk.nashorn.internal.ir;
-import jdk.internal.dynalink.beans.BeansLinker;
+import java.util.List;
+import jdk.nashorn.internal.codegen.Label;
/**
- * Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of
- * a method and a bound this, without any behavior. All the behavior is defined in the {@code BoundDynamicMethodLinker}.
+ * Interface that can be used to get a list of all labels in a node
*/
-final class BoundDynamicMethod {
- private final Object dynamicMethod;
- private final Object boundThis;
+public interface Labels {
- BoundDynamicMethod(final Object dynamicMethod, final Object boundThis) {
- assert BeansLinker.isDynamicMethod(dynamicMethod);
- this.dynamicMethod = dynamicMethod;
- this.boundThis = boundThis;
- }
-
- Object getDynamicMethod() {
- return dynamicMethod;
- }
-
- Object getBoundThis() {
- return boundThis;
- }
+ /**
+ * Return the labels associated with this node. Breakable nodes that
+ * aren't LoopNodes only have a break label - the location immediately
+ * afterwards the node in code
+ * @return list of labels representing locations around this node
+ */
+ public List<Label> getLabels();
}
diff --git a/src/jdk/nashorn/internal/ir/LexicalContext.java b/src/jdk/nashorn/internal/ir/LexicalContext.java
index 1b380d38..487d6aeb 100644
--- a/src/jdk/nashorn/internal/ir/LexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/LexicalContext.java
@@ -27,7 +27,6 @@ package jdk.nashorn.internal.ir;
import java.io.File;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import jdk.nashorn.internal.codegen.Label;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.Source;
@@ -148,6 +147,7 @@ public class LexicalContext {
* @return the node that was pushed
*/
public <T extends LexicalContextNode> T push(final T node) {
+ assert !contains(node);
if (sp == stack.length) {
final LexicalContextNode[] newStack = new LexicalContextNode[sp * 2];
System.arraycopy(stack, 0, newStack, 0, sp);
@@ -201,6 +201,18 @@ public class LexicalContext {
return (T)popped;
}
+ /**
+ * Explicitly apply flags to the topmost element on the stack. This is only valid to use from a
+ * {@code NodeVisitor.leaveXxx()} method and only on the node being exited at the time. It is not mandatory to use,
+ * as {@link #pop(LexicalContextNode)} will apply the flags automatically, but this method can be used to apply them
+ * during the {@code leaveXxx()} method in case its logic depends on the value of the flags.
+ * @param node the node to apply the flags to. Must be the topmost node on the stack.
+ * @return the passed in node, or a modified node (if any flags were modified)
+ */
+ public <T extends LexicalContextNode & Flags<T>> T applyTopFlags(final T node) {
+ assert node == peek();
+ return node.setFlag(this, flags[sp - 1]);
+ }
/**
* Return the top element in the context
@@ -233,10 +245,9 @@ public class LexicalContext {
* @return the new node
*/
public LexicalContextNode replace(final LexicalContextNode oldNode, final LexicalContextNode newNode) {
- //System.err.println("REPLACE old=" + Debug.id(oldNode) + " new=" + Debug.id(newNode));
for (int i = sp - 1; i >= 0; i--) {
if (stack[i] == oldNode) {
- assert i == (sp - 1) : "violation of contract - we always expect to find the replacement node on top of the lexical context stack: " + newNode + " has " + stack[i + 1].getClass() + " above it";
+ assert i == sp - 1 : "violation of contract - we always expect to find the replacement node on top of the lexical context stack: " + newNode + " has " + stack[i + 1].getClass() + " above it";
stack[i] = newNode;
break;
}
@@ -271,6 +282,31 @@ public class LexicalContext {
}
/**
+ * Gets the label node of the current block.
+ * @return the label node of the current block, if it is labeled. Otherwise returns null.
+ */
+ public LabelNode getCurrentBlockLabelNode() {
+ assert stack[sp - 1] instanceof Block;
+ if(sp < 2) {
+ return null;
+ }
+ final LexicalContextNode parent = stack[sp - 2];
+ return parent instanceof LabelNode ? (LabelNode)parent : null;
+ }
+
+
+ /*
+ public FunctionNode getProgram() {
+ final Iterator<FunctionNode> iter = getFunctions();
+ FunctionNode last = null;
+ while (iter.hasNext()) {
+ last = iter.next();
+ }
+ assert last != null;
+ return last;
+ }*/
+
+ /**
* Returns an iterator over all ancestors block of the given block, with its parent block first.
* @param block the block whose ancestors are returned
* @return an iterator over all ancestors block of the given block.
@@ -315,8 +351,7 @@ public class LexicalContext {
}
/**
- * Get the function for this block. If the block is itself a function
- * this returns identity
+ * Get the function for this block.
* @param block block for which to get function
* @return function for block
*/
@@ -364,9 +399,6 @@ public class LexicalContext {
* @return block in which the symbol is defined, assert if no such block in context
*/
public Block getDefiningBlock(final Symbol symbol) {
- if (symbol.isTemp()) {
- return null;
- }
final String name = symbol.getName();
for (final Iterator<Block> it = getBlocks(); it.hasNext();) {
final Block next = it.next();
@@ -382,10 +414,7 @@ public class LexicalContext {
* @param symbol symbol
* @return function node in which this symbol is defined, assert if no such symbol exists in context
*/
- public FunctionNode getDefiningFunction(Symbol symbol) {
- if (symbol.isTemp()) {
- return null;
- }
+ public FunctionNode getDefiningFunction(final Symbol symbol) {
final String name = symbol.getName();
for (final Iterator<LexicalContextNode> iter = new NodeIterator<>(LexicalContextNode.class); iter.hasNext();) {
final LexicalContextNode next = iter.next();
@@ -393,7 +422,7 @@ public class LexicalContext {
while (iter.hasNext()) {
final LexicalContextNode next2 = iter.next();
if (next2 instanceof FunctionNode) {
- return ((FunctionNode)next2);
+ return (FunctionNode)next2;
}
}
throw new AssertionError("Defining block for symbol " + name + " has no function in the context");
@@ -411,19 +440,11 @@ public class LexicalContext {
}
/**
- * Returns true if the expression defining the function is a callee of a CallNode that should be the second
- * element on the stack, e.g. <code>(function(){})()</code>. That is, if the stack ends with
- * {@code [..., CallNode, FunctionNode]} then {@code callNode.getFunction()} should be equal to
- * {@code functionNode}, and the top of the stack should itself be a variant of {@code functionNode}.
- * @param functionNode the function node being tested
- * @return true if the expression defining the current function is a callee of a call expression.
+ * Is the topmost lexical context element body of a SplitNode?
+ * @return true if it's the body of a split node.
*/
- public boolean isFunctionDefinedInCurrentCall(FunctionNode functionNode) {
- final LexicalContextNode parent = stack[sp - 2];
- if (parent instanceof CallNode && ((CallNode)parent).getFunction() == functionNode) {
- return true;
- }
- return false;
+ public boolean isSplitBody() {
+ return sp >= 2 && stack[sp - 1] instanceof Block && stack[sp - 2] instanceof SplitNode;
}
/**
@@ -444,15 +465,26 @@ public class LexicalContext {
}
/**
- * Count the number of with scopes until a given node
- * @param until node to stop counting at, or null if all nodes should be counted
+ * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of
+ * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode
+ * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location
+ * and the break/continue target.
+ * @param until node to stop counting at. Must be within the current function
* @return number of with scopes encountered in the context
*/
public int getScopeNestingLevelTo(final LexicalContextNode until) {
+ assert until != null;
//count the number of with nodes until "until" is hit
int n = 0;
- for (final Iterator<WithNode> iter = new NodeIterator<>(WithNode.class, until); iter.hasNext(); iter.next()) {
- n++;
+ for (final Iterator<LexicalContextNode> iter = getAllNodes(); iter.hasNext();) {
+ final LexicalContextNode node = iter.next();
+ if (node == until) {
+ break;
+ }
+ assert !(node instanceof FunctionNode); // Can't go outside current function
+ if (node instanceof WithNode || node instanceof Block && ((Block)node).needsScope()) {
+ n++;
+ }
}
return n;
}
@@ -486,12 +518,13 @@ public class LexicalContext {
/**
* Find the breakable node corresponding to this label.
- * @param label label to search for, if null the closest breakable node will be returned unconditionally, e.g. a while loop with no label
+ * @param labelName name of the label to search for. If null, the closest breakable node will be returned
+ * unconditionally, e.g. a while loop with no label
* @return closest breakable node
*/
- public BreakableNode getBreakable(final IdentNode label) {
- if (label != null) {
- final LabelNode foundLabel = findLabel(label.getName());
+ public BreakableNode getBreakable(final String labelName) {
+ if (labelName != null) {
+ final LabelNode foundLabel = findLabel(labelName);
if (foundLabel != null) {
// iterate to the nearest breakable to the foundLabel
BreakableNode breakable = null;
@@ -511,12 +544,13 @@ public class LexicalContext {
/**
* Find the continue target node corresponding to this label.
- * @param label label to search for, if null the closest loop node will be returned unconditionally, e.g. a while loop with no label
+ * @param labelName label name to search for. If null the closest loop node will be returned unconditionally, e.g. a
+ * while loop with no label
* @return closest continue target node
*/
- public LoopNode getContinueTo(final IdentNode label) {
- if (label != null) {
- final LabelNode foundLabel = findLabel(label.getName());
+ public LoopNode getContinueTo(final String labelName) {
+ if (labelName != null) {
+ final LabelNode foundLabel = findLabel(labelName);
if (foundLabel != null) {
// iterate to the nearest loop to the foundLabel
LoopNode loop = null;
@@ -538,7 +572,7 @@ public class LexicalContext {
public LabelNode findLabel(final String name) {
for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
final LabelNode next = iter.next();
- if (next.getLabel().getName().equals(name)) {
+ if (next.getLabelName().equals(name)) {
return next;
}
}
@@ -546,30 +580,34 @@ public class LexicalContext {
}
/**
- * Checks whether a given label is a jump destination that lies outside a given
- * split node
+ * Checks whether a given target is a jump destination that lies outside a given split node
* @param splitNode the split node
- * @param label the label
- * @return true if label resides outside the split node
+ * @param target the target node
+ * @return true if target resides outside the split node
*/
- public boolean isExternalTarget(final SplitNode splitNode, final Label label) {
- boolean targetFound = false;
- for (int i = sp - 1; i >= 0; i--) {
+ public boolean isExternalTarget(final SplitNode splitNode, final BreakableNode target) {
+ for (int i = sp; i-- > 0;) {
final LexicalContextNode next = stack[i];
if (next == splitNode) {
- return !targetFound;
+ return true;
+ } else if (next == target) {
+ return false;
}
+ }
+ throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
+ }
- if (next instanceof BreakableNode) {
- for (final Label l : ((BreakableNode)next).getLabels()) {
- if (l == label) {
- targetFound = true;
- break;
- }
- }
+ /**
+ * Checks whether the current context is inside a switch statement without explicit blocks (curly braces).
+ * @return true if in unprotected switch statement
+ */
+ public boolean inUnprotectedSwitchContext() {
+ for (int i = sp; i > 0; i--) {
+ final LexicalContextNode next = stack[i];
+ if (next instanceof Block) {
+ return stack[i - 1] instanceof SwitchNode;
}
}
- assert false : label + " was expected in lexical context " + LexicalContext.this + " but wasn't";
return false;
}
@@ -627,11 +665,12 @@ public class LexicalContext {
if (next == null) {
throw new NoSuchElementException();
}
- T lnext = next;
+ final T lnext = next;
next = findNext();
return lnext;
}
+ @SuppressWarnings("unchecked")
private T findNext() {
for (int i = index; i >= 0; i--) {
final Object node = stack[i];
@@ -640,7 +679,7 @@ public class LexicalContext {
}
if (clazz.isAssignableFrom(node.getClass())) {
index = i - 1;
- return clazz.cast(node);
+ return (T)node;
}
}
return null;
diff --git a/src/jdk/nashorn/internal/ir/LexicalContextExpression.java b/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
index d3c77777..e9a88cc8 100644
--- a/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
+++ b/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
@@ -28,16 +28,17 @@ package jdk.nashorn.internal.ir;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
abstract class LexicalContextExpression extends Expression implements LexicalContextNode {
+ private static final long serialVersionUID = 1L;
- LexicalContextExpression(LexicalContextExpression expr) {
+ LexicalContextExpression(final LexicalContextExpression expr) {
super(expr);
}
- LexicalContextExpression(long token, int start, int finish) {
+ LexicalContextExpression(final long token, final int start, final int finish) {
super(token, start, finish);
}
- LexicalContextExpression(long token, int finish) {
+ LexicalContextExpression(final long token, final int finish) {
super(token, finish);
}
@@ -45,15 +46,4 @@ abstract class LexicalContextExpression extends Expression implements LexicalCon
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
return Acceptor.accept(this, visitor);
}
-
- /**
- * Set the symbol and replace in lexical context if applicable
- * @param lc lexical context
- * @param symbol symbol
- * @return new node if symbol changed
- */
- @Override
- public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
- return Node.replaceInLexicalContext(lc, this, (LexicalContextExpression)super.setSymbol(null, symbol));
- }
}
diff --git a/src/jdk/nashorn/internal/ir/LexicalContextStatement.java b/src/jdk/nashorn/internal/ir/LexicalContextStatement.java
index c7bbfb2f..6a65fad2 100644
--- a/src/jdk/nashorn/internal/ir/LexicalContextStatement.java
+++ b/src/jdk/nashorn/internal/ir/LexicalContextStatement.java
@@ -28,6 +28,8 @@ package jdk.nashorn.internal.ir;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
abstract class LexicalContextStatement extends Statement implements LexicalContextNode {
+ private static final long serialVersionUID = 1L;
+
/**
* Constructor
*
diff --git a/src/jdk/nashorn/internal/ir/LiteralNode.java b/src/jdk/nashorn/internal/ir/LiteralNode.java
index 8d6823cb..6aee20cd 100644
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java
@@ -25,10 +25,11 @@
package jdk.nashorn.internal.ir;
+import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
@@ -49,6 +50,8 @@ import jdk.nashorn.internal.runtime.Undefined;
*/
@Immutable
public abstract class LiteralNode<T> extends Expression implements PropertyKey {
+ private static final long serialVersionUID = 1L;
+
/** Literal value */
protected final T value;
@@ -86,9 +89,15 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
this.value = newValue;
}
- @Override
- public boolean isAtom() {
- return true;
+ /**
+ * Initialization setter, if required for immutable state. This is used for
+ * things like ArrayLiteralNodes that need to carry state for the splitter.
+ * Default implementation is just a nop.
+ * @param lc lexical context
+ * @return new literal node with initialized state, or same if nothing changed
+ */
+ public LiteralNode<?> initialize(final LexicalContext lc) {
+ return this;
}
/**
@@ -100,7 +109,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return Type.typeFor(value.getClass());
}
@@ -215,7 +224,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
if (value == null) {
sb.append("null");
} else {
@@ -227,10 +236,14 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* Get the literal node value
* @return the value
*/
- public T getValue() {
+ public final T getValue() {
return value;
}
+ private static Expression[] valueToArray(final List<Expression> value) {
+ return value.toArray(new Expression[value.size()]);
+ }
+
/**
* Create a new null literal
*
@@ -260,6 +273,8 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* @param <T> the literal type
*/
public static class PrimitiveLiteralNode<T> extends LiteralNode<T> {
+ private static final long serialVersionUID = 1L;
+
private PrimitiveLiteralNode(final long token, final int finish, final T value) {
super(token, finish, value);
}
@@ -280,10 +295,21 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
public boolean isLocal() {
return true;
}
+
+ @Override
+ public boolean isAlwaysFalse() {
+ return !isTrue();
+ }
+
+ @Override
+ public boolean isAlwaysTrue() {
+ return isTrue();
+ }
}
@Immutable
private static final class BooleanLiteralNode extends PrimitiveLiteralNode<Boolean> {
+ private static final long serialVersionUID = 1L;
private BooleanLiteralNode(final long token, final int finish, final boolean value) {
super(Token.recast(token, value ? TokenType.TRUE : TokenType.FALSE), finish, value);
@@ -299,7 +325,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return Type.BOOLEAN;
}
@@ -336,6 +362,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
@Immutable
private static final class NumberLiteralNode extends PrimitiveLiteralNode<Number> {
+ private static final long serialVersionUID = 1L;
private final Type type = numberGetType(value);
@@ -362,7 +389,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return type;
}
@@ -398,6 +425,8 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
private static class UndefinedLiteralNode extends PrimitiveLiteralNode<Undefined> {
+ private static final long serialVersionUID = 1L;
+
private UndefinedLiteralNode(final long token, final int finish) {
super(Token.recast(token, TokenType.OBJECT), finish, ScriptRuntime.UNDEFINED);
}
@@ -434,6 +463,8 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
@Immutable
private static class StringLiteralNode extends PrimitiveLiteralNode<String> {
+ private static final long serialVersionUID = 1L;
+
private StringLiteralNode(final long token, final int finish, final String value) {
super(Token.recast(token, TokenType.STRING), finish, value);
}
@@ -443,7 +474,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append('\"');
sb.append(value);
sb.append('\"');
@@ -477,6 +508,8 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
@Immutable
private static class LexerTokenLiteralNode extends LiteralNode<LexerToken> {
+ private static final long serialVersionUID = 1L;
+
private LexerTokenLiteralNode(final long token, final int finish, final LexerToken value) {
super(Token.recast(token, TokenType.STRING), finish, value); //TODO is string the correct token type here?
}
@@ -486,12 +519,12 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return Type.OBJECT;
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append(value.toString());
}
}
@@ -540,6 +573,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
+ private static final long serialVersionUID = 1L;
private NullLiteralNode(final long token, final int finish) {
super(Token.recast(token, TokenType.OBJECT), finish, null);
@@ -555,7 +589,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return Type.OBJECT;
}
@@ -568,24 +602,29 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
/**
* Array literal node class.
*/
- public static final class ArrayLiteralNode extends LiteralNode<Expression[]> {
+ @Immutable
+ public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
+ private static final long serialVersionUID = 1L;
/** Array element type. */
- private Type elementType;
+ private final Type elementType;
/** Preset constant array. */
- private Object presets;
+ private final Object presets;
/** Indices of array elements requiring computed post sets. */
- private int[] postsets;
+ private final int[] postsets;
- private List<ArrayUnit> units;
+ /** Sub units with indexes ranges, in which to split up code generation, for large literals */
+ private final List<ArrayUnit> units;
/**
* An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
* be split if they are too large, for bytecode generation reasons
*/
- public static class ArrayUnit {
+ public static final class ArrayUnit implements CompileUnitHolder, Serializable {
+ private static final long serialVersionUID = 1L;
+
/** Compile unit associated with the postsets range. */
private final CompileUnit compileUnit;
@@ -624,159 +663,181 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* The array compile unit
* @return array compile unit
*/
+ @Override
public CompileUnit getCompileUnit() {
return compileUnit;
}
}
- /**
- * Constructor
- *
- * @param token token
- * @param finish finish
- * @param value array literal value, a Node array
- */
- protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
- super(Token.recast(token, TokenType.ARRAY), finish, value);
- this.elementType = Type.UNKNOWN;
- }
+ private static final class ArrayLiteralInitializer {
- /**
- * Copy constructor
- * @param node source array literal node
- */
- private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value) {
- super(node, value);
- this.elementType = node.elementType;
- this.presets = node.presets;
- this.postsets = node.postsets;
- this.units = node.units;
- }
-
- /**
- * Compute things like widest element type needed. Internal use from compiler only
- */
- public void analyze() {
- elementType = Type.INT;
- analyzeElements();
-
- if (elementType.isInteger()) {
- presetIntArray();
- } else if (elementType.isLong()) {
- presetLongArray();
- } else if (elementType.isNumeric()) {
- presetNumberArray();
- } else {
- presetObjectArray();
+ static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
+ final Type elementType = computeElementType(node.value);
+ final int[] postsets = computePostsets(node.value);
+ final Object presets = computePresets(node.value, elementType, postsets);
+ return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
}
- }
- private void presetIntArray() {
- final int[] array = new int[value.length];
- final int[] computed = new int[value.length];
- int nComputed = 0;
+ private static Type computeElementType(final Expression[] value) {
+ Type widestElementType = Type.INT;
- for (int i = 0; i < value.length; i++) {
- final Object element = objectAsConstant(value[i]);
+ for (final Expression elem : value) {
+ if (elem == null) {
+ widestElementType = widestElementType.widest(Type.OBJECT); //no way to represent undefined as number
+ break;
+ }
- if (element instanceof Number) {
- array[i] = ((Number)element).intValue();
- } else {
- computed[nComputed++] = i;
+ final Type type = elem.getType().isUnknown() ? Type.OBJECT : elem.getType();
+ if (type.isBoolean()) {
+ //TODO fix this with explicit boolean types
+ widestElementType = widestElementType.widest(Type.OBJECT);
+ break;
+ }
+
+ widestElementType = widestElementType.widest(type);
+ if (widestElementType.isObject()) {
+ break;
+ }
}
+ return widestElementType;
}
- presets = array;
- postsets = Arrays.copyOf(computed, nComputed);
- }
-
- private void presetLongArray() {
- final long[] array = new long[value.length];
- final int[] computed = new int[value.length];
- int nComputed = 0;
+ private static int[] computePostsets(final Expression[] value) {
+ final int[] computed = new int[value.length];
+ int nComputed = 0;
- for (int i = 0; i < value.length; i++) {
- final Object element = objectAsConstant(value[i]);
+ for (int i = 0; i < value.length; i++) {
+ final Expression element = value[i];
+ if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
+ computed[nComputed++] = i;
+ }
+ }
+ return Arrays.copyOf(computed, nComputed);
+ }
- if (element instanceof Number) {
- array[i] = ((Number)element).longValue();
- } else {
- computed[nComputed++] = i;
+ private static boolean setArrayElement(final int[] array, final int i, final Object n) {
+ if (n instanceof Number) {
+ array[i] = ((Number)n).intValue();
+ return true;
}
+ return false;
}
- presets = array;
- postsets = Arrays.copyOf(computed, nComputed);
- }
+ private static boolean setArrayElement(final long[] array, final int i, final Object n) {
+ if (n instanceof Number) {
+ array[i] = ((Number)n).longValue();
+ return true;
+ }
+ return false;
+ }
- private void presetNumberArray() {
- final double[] array = new double[value.length];
- final int[] computed = new int[value.length];
- int nComputed = 0;
+ private static boolean setArrayElement(final double[] array, final int i, final Object n) {
+ if (n instanceof Number) {
+ array[i] = ((Number)n).doubleValue();
+ return true;
+ }
+ return false;
+ }
- for (int i = 0; i < value.length; i++) {
- final Object element = objectAsConstant(value[i]);
+ private static int[] presetIntArray(final Expression[] value, final int[] postsets) {
+ final int[] array = new int[value.length];
+ int nComputed = 0;
+ for (int i = 0; i < value.length; i++) {
+ if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+ assert postsets[nComputed++] == i;
+ }
+ }
+ assert postsets.length == nComputed;
+ return array;
+ }
- if (element instanceof Number) {
- array[i] = ((Number)element).doubleValue();
- } else {
- computed[nComputed++] = i;
+ private static long[] presetLongArray(final Expression[] value, final int[] postsets) {
+ final long[] array = new long[value.length];
+ int nComputed = 0;
+ for (int i = 0; i < value.length; i++) {
+ if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+ assert postsets[nComputed++] == i;
+ }
}
+ assert postsets.length == nComputed;
+ return array;
}
- presets = array;
- postsets = Arrays.copyOf(computed, nComputed);
- }
+ private static double[] presetDoubleArray(final Expression[] value, final int[] postsets) {
+ final double[] array = new double[value.length];
+ int nComputed = 0;
+ for (int i = 0; i < value.length; i++) {
+ if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+ assert postsets[nComputed++] == i;
+ }
+ }
+ assert postsets.length == nComputed;
+ return array;
+ }
- private void presetObjectArray() {
- final Object[] array = new Object[value.length];
- final int[] computed = new int[value.length];
- int nComputed = 0;
+ private static Object[] presetObjectArray(final Expression[] value, final int[] postsets) {
+ final Object[] array = new Object[value.length];
+ int nComputed = 0;
- for (int i = 0; i < value.length; i++) {
- final Node node = value[i];
+ for (int i = 0; i < value.length; i++) {
+ final Node node = value[i];
- if (node == null) {
- computed[nComputed++] = i;
- } else {
+ if (node == null) {
+ assert postsets[nComputed++] == i;
+ continue;
+ }
final Object element = objectAsConstant(node);
if (element != POSTSET_MARKER) {
array[i] = element;
} else {
- computed[nComputed++] = i;
+ assert postsets[nComputed++] == i;
}
}
- }
-
- presets = array;
- postsets = Arrays.copyOf(computed, nComputed);
- }
- private void analyzeElements() {
- for (final Expression node : value) {
- if (node == null) {
- elementType = elementType.widest(Type.OBJECT); //no way to represent undefined as number
- break;
- }
-
- assert node.getSymbol() != null; //don't run this on unresolved nodes or you are in trouble
- Type symbolType = node.getSymbol().getSymbolType();
- if (symbolType.isUnknown()) {
- symbolType = Type.OBJECT;
- }
+ assert postsets.length == nComputed;
+ return array;
+ }
- if (symbolType.isBoolean()) {
- elementType = elementType.widest(Type.OBJECT);
- break;
+ static Object computePresets(final Expression[] value, final Type elementType, final int[] postsets) {
+ assert !elementType.isUnknown();
+ if (elementType.isInteger()) {
+ return presetIntArray(value, postsets);
+ } else if (elementType.isLong()) {
+ return presetLongArray(value, postsets);
+ } else if (elementType.isNumeric()) {
+ return presetDoubleArray(value, postsets);
+ } else {
+ return presetObjectArray(value, postsets);
}
+ }
+ }
- elementType = elementType.widest(symbolType);
+ /**
+ * Constructor
+ *
+ * @param token token
+ * @param finish finish
+ * @param value array literal value, a Node array
+ */
+ protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
+ super(Token.recast(token, TokenType.ARRAY), finish, value);
+ this.elementType = Type.UNKNOWN;
+ this.presets = null;
+ this.postsets = null;
+ this.units = null;
+ }
- if (elementType.isObject()) {
- break;
- }
- }
+ /**
+ * Copy constructor
+ * @param node source array literal node
+ */
+ private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
+ super(node, value);
+ this.elementType = elementType;
+ this.postsets = postsets;
+ this.presets = presets;
+ this.units = units;
}
@Override
@@ -785,10 +846,27 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
/**
+ * Setter that initializes all code generation meta data for an
+ * ArrayLiteralNode. This acts a setter, so the return value may
+ * return a new node and must be handled
+ *
+ * @param lc lexical context
+ * @return new array literal node with postsets, presets and element types initialized
+ */
+ @Override
+ public ArrayLiteralNode initialize(final LexicalContext lc) {
+ return Node.replaceInLexicalContext(lc, this, ArrayLiteralInitializer.initialize(this));
+ }
+
+ /**
* Get the array element type as Java format, e.g. [I
* @return array element type
*/
public ArrayType getArrayType() {
+ return getArrayType(getElementType());
+ }
+
+ private static ArrayType getArrayType(final Type elementType) {
if (elementType.isInteger()) {
return Type.INT_ARRAY;
} else if (elementType.isLong()) {
@@ -801,7 +879,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
}
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return Type.typeFor(NativeArray.class);
}
@@ -810,6 +888,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* @return element type
*/
public Type getElementType() {
+ assert !elementType.isUnknown() : this + " has elementType=unknown";
return elementType;
}
@@ -819,14 +898,28 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* @return post set indices
*/
public int[] getPostsets() {
+ assert postsets != null : this + " elementType=" + elementType + " has no postsets";
return postsets;
}
+ private boolean presetsMatchElementType() {
+ if (elementType == Type.INT) {
+ return presets instanceof int[];
+ } else if (elementType == Type.LONG) {
+ return presets instanceof long[];
+ } else if (elementType == Type.NUMBER) {
+ return presets instanceof double[];
+ } else {
+ return presets instanceof Object[];
+ }
+ }
+
/**
* Get presets constant array
* @return presets array, always returns an array type
*/
public Object getPresets() {
+ assert presets != null && presetsMatchElementType() : this + " doesn't have presets, or invalid preset type: " + presets;
return presets;
}
@@ -841,29 +934,46 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
/**
* Set the ArrayUnits that make up this ArrayLiteral
+ * @param lc lexical context
* @see ArrayUnit
* @param units list of array units
+ * @return new or changed arrayliteralnode
*/
- public void setUnits(final List<ArrayUnit> units) {
- this.units = units;
+ public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
+ if (this.units == units) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ return Acceptor.accept(this, visitor);
+ }
+
+ @Override
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
final List<Expression> oldValue = Arrays.asList(value);
- final List<Expression> newValue = Node.accept(visitor, Expression.class, oldValue);
- return visitor.leaveLiteralNode(oldValue != newValue ? setValue(newValue) : this);
+ final List<Expression> newValue = Node.accept(visitor, oldValue);
+ return visitor.leaveLiteralNode(oldValue != newValue ? setValue(lc, newValue) : this);
}
return this;
}
- private ArrayLiteralNode setValue(final List<Expression> value) {
- return new ArrayLiteralNode(this, value.toArray(new Expression[value.size()]));
+ private ArrayLiteralNode setValue(final LexicalContext lc, final Expression[] value) {
+ if (this.value == value) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+ }
+
+ private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
+ return setValue(lc, value.toArray(new Expression[value.size()]));
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append('[');
boolean first = true;
for (final Node node : value) {
@@ -874,7 +984,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
if (node == null) {
sb.append("undefined");
} else {
- node.toString(sb);
+ node.toString(sb, printType);
}
first = false;
}
@@ -892,10 +1002,9 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* @return the new literal node
*/
public static LiteralNode<Expression[]> newInstance(final long token, final int finish, final List<Expression> value) {
- return new ArrayLiteralNode(token, finish, value.toArray(new Expression[value.size()]));
+ return new ArrayLiteralNode(token, finish, valueToArray(value));
}
-
/**
* Create a new array literal based on a parent node (source, token, finish)
*
@@ -905,7 +1014,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
* @return the new literal node
*/
public static LiteralNode<?> newInstance(final Node parent, final List<Expression> value) {
- return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), value.toArray(new Expression[value.size()]));
+ return new ArrayLiteralNode(parent.getToken(), parent.getFinish(), valueToArray(value));
}
/**
diff --git a/src/jdk/nashorn/internal/ir/LocalVariableConversion.java b/src/jdk/nashorn/internal/ir/LocalVariableConversion.java
new file mode 100644
index 00000000..b66a2fd9
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/LocalVariableConversion.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Class describing one or more local variable conversions that needs to be performed on entry to a control flow join
+ * point. Note that the class is named as a singular "Conversion" and not a plural "Conversions", but instances of the
+ * class have a reference to the next conversion, so multiple conversions are always represented with a single instance
+ * that is a head of a linked list of instances.
+ * @see JoinPredecessor
+ */
+public final class LocalVariableConversion {
+ private final Symbol symbol;
+ // TODO: maybe introduce a type pair class? These will often be repeated.
+ private final Type from;
+ private final Type to;
+ private final LocalVariableConversion next;
+
+ /**
+ * Creates a new object representing a local variable conversion.
+ * @param symbol the symbol representing the local variable whose value is being converted.
+ * @param from the type value is being converted from.
+ * @param to the type value is being converted to.
+ * @param next next conversion at the same join point, if any (the conversion object implements a singly-linked
+ * list of conversions).
+ */
+ public LocalVariableConversion(final Symbol symbol, final Type from, final Type to, final LocalVariableConversion next) {
+ this.symbol = symbol;
+ this.from = from;
+ this.to = to;
+ this.next = next;
+ }
+
+ /**
+ * Returns the type being converted from.
+ * @return the type being converted from.
+ */
+ public Type getFrom() {
+ return from;
+ }
+
+ /**
+ * Returns the type being converted to.
+ * @return the type being converted to.
+ */
+ public Type getTo() {
+ return to;
+ }
+
+ /**
+ * Returns the next conversion at the same join point, or null if this is the last one.
+ * @return the next conversion at the same join point.
+ */
+ public LocalVariableConversion getNext() {
+ return next;
+ }
+
+ /**
+ * Returns the symbol representing the local variable whose value is being converted.
+ * @return the symbol representing the local variable whose value is being converted.
+ */
+ public Symbol getSymbol() {
+ return symbol;
+ }
+
+ /**
+ * Returns true if this conversion is live. A conversion is live if the symbol has a slot for the conversion's
+ * {@link #getTo() to} type. If a conversion is dead, it can be omitted in code generator.
+ * @return true if this conversion is live.
+ */
+ public boolean isLive() {
+ return symbol.hasSlotFor(to);
+ }
+
+ /**
+ * Returns true if this conversion {@link #isLive()}, or if any of its {@link #getNext()} conversions are live.
+ * @return true if this conversion, or any conversion following it, are live.
+ */
+ public boolean isAnyLive() {
+ return isLive() || isAnyLive(next);
+ }
+
+ /**
+ * Returns true if the passed join predecessor has {@link #isAnyLive()} conversion.
+ * @param jp the join predecessor being examined.
+ * @return true if the join predecessor conversion is not null and {@link #isAnyLive()}.
+ */
+ public static boolean hasLiveConversion(final JoinPredecessor jp) {
+ return isAnyLive(jp.getLocalVariableConversion());
+ }
+
+ /**
+ * Returns true if the passed conversion is not null, and it {@link #isAnyLive()}.
+ * @parameter conv the conversion being tested for liveness.
+ * @return true if the conversion is not null and {@link #isAnyLive()}.
+ */
+ private static boolean isAnyLive(final LocalVariableConversion conv) {
+ return conv != null && conv.isAnyLive();
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+
+ /**
+ * Generates a string representation of this conversion in the passed string builder.
+ * @param sb the string builder in which to generate a string representation of this conversion.
+ * @return the passed in string builder.
+ */
+ public StringBuilder toString(final StringBuilder sb) {
+ if(isLive()) {
+ return toStringNext(sb.append('\u27e6'), true).append("\u27e7 ");
+ }
+ return next == null ? sb : next.toString(sb);
+ }
+
+ /**
+ * Generates a string representation of the passed conversion in the passed string builder.
+ * @param conv the conversion to render in the string builder.
+ * @param sb the string builder in which to generate a string representation of this conversion.
+ * @return the passed in string builder.
+ */
+ public static StringBuilder toString(final LocalVariableConversion conv, final StringBuilder sb) {
+ return conv == null ? sb : conv.toString(sb);
+ }
+
+ private StringBuilder toStringNext(final StringBuilder sb, final boolean first) {
+ if(isLive()) {
+ if(!first) {
+ sb.append(", ");
+ }
+ sb.append(symbol.getName()).append(':').append(getTypeChar(from)).append('\u2192').append(getTypeChar(to));
+ return next == null ? sb : next.toStringNext(sb, false);
+ }
+ return next == null ? sb : next.toStringNext(sb, first);
+ }
+
+ private static char getTypeChar(final Type type) {
+ if(type == Type.UNDEFINED) {
+ return 'U';
+ } else if(type.isObject()) {
+ return 'O';
+ } else if(type == Type.BOOLEAN) {
+ return 'Z';
+ }
+ return type.getBytecodeStackType();
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/LoopNode.java b/src/jdk/nashorn/internal/ir/LoopNode.java
index 107030a2..5991a32a 100644
--- a/src/jdk/nashorn/internal/ir/LoopNode.java
+++ b/src/jdk/nashorn/internal/ir/LoopNode.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.ir;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.codegen.Label;
@@ -33,11 +34,13 @@ import jdk.nashorn.internal.codegen.Label;
* A loop node, for example a while node, do while node or for node
*/
public abstract class LoopNode extends BreakableStatement {
+ private static final long serialVersionUID = 1L;
+
/** loop continue label. */
protected final Label continueLabel;
/** Loop test node, null if infinite */
- protected final Expression test;
+ protected final JoinPredecessorExpression test;
/** Loop body */
protected final Block body;
@@ -51,14 +54,13 @@ public abstract class LoopNode extends BreakableStatement {
* @param lineNumber lineNumber
* @param token token
* @param finish finish
- * @param test test, or null if infinite loop
* @param body loop body
* @param controlFlowEscapes controlFlowEscapes
*/
- protected LoopNode(final int lineNumber, final long token, final int finish, final Expression test, final Block body, final boolean controlFlowEscapes) {
+ protected LoopNode(final int lineNumber, final long token, final int finish, final Block body, final boolean controlFlowEscapes) {
super(lineNumber, token, finish, new Label("while_break"));
this.continueLabel = new Label("while_continue");
- this.test = test;
+ this.test = null;
this.body = body;
this.controlFlowEscapes = controlFlowEscapes;
}
@@ -70,9 +72,11 @@ public abstract class LoopNode extends BreakableStatement {
* @param test new test
* @param body new body
* @param controlFlowEscapes controlFlowEscapes
+ * @param conversion the local variable conversion carried by this loop node.
*/
- protected LoopNode(final LoopNode loopNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
- super(loopNode);
+ protected LoopNode(final LoopNode loopNode, final JoinPredecessorExpression test, final Block body,
+ final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+ super(loopNode, conversion);
this.continueLabel = new Label(loopNode.continueLabel);
this.test = test;
this.body = body;
@@ -125,7 +129,7 @@ public abstract class LoopNode extends BreakableStatement {
@Override
public List<Label> getLabels() {
- return Arrays.asList(breakLabel, continueLabel);
+ return Collections.unmodifiableList(Arrays.asList(breakLabel, continueLabel));
}
@Override
@@ -150,7 +154,9 @@ public abstract class LoopNode extends BreakableStatement {
* Get the test for this for node
* @return the test
*/
- public abstract Expression getTest();
+ public final JoinPredecessorExpression getTest() {
+ return test;
+ }
/**
* Set the test for this for node
@@ -159,7 +165,7 @@ public abstract class LoopNode extends BreakableStatement {
* @param test new test
* @return same or new node depending on if test was changed
*/
- public abstract LoopNode setTest(final LexicalContext lc, final Expression test);
+ public abstract LoopNode setTest(final LexicalContext lc, final JoinPredecessorExpression test);
/**
* Set the control flow escapes flag for this node.
@@ -171,4 +177,9 @@ public abstract class LoopNode extends BreakableStatement {
*/
public abstract LoopNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes);
+ /**
+ * Does this loop have a LET declaration and hence require a per-iteration scope?
+ * @return true if a per-iteration scope is required.
+ */
+ public abstract boolean hasPerIterationScope();
}
diff --git a/src/jdk/nashorn/internal/ir/Node.java b/src/jdk/nashorn/internal/ir/Node.java
index c59c235b..d6c57655 100644
--- a/src/jdk/nashorn/internal/ir/Node.java
+++ b/src/jdk/nashorn/internal/ir/Node.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.ir;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
@@ -35,7 +35,18 @@ import jdk.nashorn.internal.parser.TokenType;
/**
* Nodes are used to compose Abstract Syntax Trees.
*/
-public abstract class Node implements Cloneable {
+public abstract class Node implements Cloneable, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /** Constant used for synthetic AST nodes that have no line number. */
+ public static final int NO_LINE_NUMBER = -1;
+
+ /** Constant used for synthetic AST nodes that have no token. */
+ public static final long NO_TOKEN = 0L;
+
+ /** Constant used for synthetic AST nodes that have no finish. */
+ public static final int NO_FINISH = 0;
+
/** Start of source range. */
protected final int start;
@@ -82,15 +93,6 @@ public abstract class Node implements Cloneable {
}
/**
- * Is this an atom node - for example a literal or an identity
- *
- * @return true if atom
- */
- public boolean isAtom() {
- return false;
- }
-
- /**
* Is this a loop node?
*
* @return true if atom
@@ -110,31 +112,6 @@ public abstract class Node implements Cloneable {
}
/**
- * Is this a self modifying assignment?
- * @return true if self modifying, e.g. a++, or a*= 17
- */
- public boolean isSelfModifying() {
- return false;
- }
-
- /**
- * Returns widest operation type of this operation.
- *
- * @return the widest type for this operation
- */
- public Type getWidestOperationType() {
- return Type.OBJECT;
- }
-
- /**
- * Returns true if this node represents a comparison operator
- * @return true if comparison
- */
- public boolean isComparison() {
- return false;
- }
-
- /**
* For reference copies - ensure that labels in the copy node are unique
* using an appropriate copy constructor
* @param lc lexical context
@@ -164,16 +141,19 @@ public abstract class Node implements Cloneable {
*
* @param sb a StringBuilder
*/
- public abstract void toString(StringBuilder sb);
+ public void toString(final StringBuilder sb) {
+ toString(sb, true);
+ }
/**
- * Check if this node has terminal flags, i.e. ends or breaks control flow
- *
- * @return true if terminal
+ * Print logic that decides whether to show the optimistic type
+ * or not - for example it should not be printed after just parse,
+ * when it hasn't been computed, or has been set to a trivially provable
+ * value
+ * @param sb string builder
+ * @param printType print type?
*/
- public boolean hasTerminalFlags() {
- return isTerminal() || hasGoto();
- }
+ public abstract void toString(final StringBuilder sb, final boolean printType);
/**
* Get the finish position for this node in the source string
@@ -192,15 +172,6 @@ public abstract class Node implements Cloneable {
}
/**
- * Check if this function repositions control flow with goto like
- * semantics, for example {@link BreakNode} or a {@link ForNode} with no test
- * @return true if node has goto semantics
- */
- public boolean hasGoto() {
- return false;
- }
-
- /**
* Get start position for node
* @return start position
*/
@@ -219,12 +190,15 @@ public abstract class Node implements Cloneable {
@Override
public final boolean equals(final Object other) {
- return super.equals(other);
+ return this == other;
}
@Override
public final int hashCode() {
- return super.hashCode();
+ // NOTE: we aren't delegating to Object.hashCode as it still requires trip to the VM for initializing,
+ // it touches the object header and/or stores the identity hashcode somewhere, etc. There's several
+ // places in the compiler pipeline that store nodes in maps, so this can get hot.
+ return Long.hashCode(token);
}
/**
@@ -272,30 +246,35 @@ public abstract class Node implements Cloneable {
return token;
}
- /**
- * Is this a terminal Node, i.e. does it end control flow like a throw or return
- * expression does?
- *
- * @return true if this node is terminal
- */
- public boolean isTerminal() {
- return false;
- }
-
//on change, we have to replace the entire list, that's we can't simple do ListIterator.set
- static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) {
- boolean changed = false;
- final List<T> newList = new ArrayList<>();
+ static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final List<T> list) {
+ final int size = list.size();
+ if (size == 0) {
+ return list;
+ }
+
+ List<T> newList = null;
- for (final Node node : list) {
- final T newNode = node == null ? null : clazz.cast(node.accept(visitor));
+ for (int i = 0; i < size; i++) {
+ final T node = list.get(i);
+ @SuppressWarnings("unchecked")
+ final T newNode = node == null ? null : (T)node.accept(visitor);
if (newNode != node) {
- changed = true;
+ if (newList == null) {
+ newList = new ArrayList<>(size);
+ for (int j = 0; j < i; j++) {
+ newList.add(list.get(j));
+ }
+ }
+ newList.add(newNode);
+ } else {
+ if (newList != null) {
+ newList.add(node);
+ }
}
- newList.add(newNode);
}
- return changed ? newList : list;
+ return newList == null ? list : newList;
}
static <T extends LexicalContextNode> T replaceInLexicalContext(final LexicalContext lc, final T oldNode, final T newNode) {
diff --git a/src/jdk/nashorn/internal/ir/ObjectNode.java b/src/jdk/nashorn/internal/ir/ObjectNode.java
index b46e9b31..d5bd78b5 100644
--- a/src/jdk/nashorn/internal/ir/ObjectNode.java
+++ b/src/jdk/nashorn/internal/ir/ObjectNode.java
@@ -27,6 +27,8 @@ package jdk.nashorn.internal.ir;
import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -35,6 +37,7 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class ObjectNode extends Expression {
+ private static final long serialVersionUID = 1L;
/** Literal elements. */
private final List<PropertyNode> elements;
@@ -59,14 +62,19 @@ public final class ObjectNode extends Expression {
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterObjectNode(this)) {
- return visitor.leaveObjectNode(setElements(Node.accept(visitor, PropertyNode.class, elements)));
+ return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append('{');
if (!elements.isEmpty()) {
@@ -79,7 +87,7 @@ public final class ObjectNode extends Expression {
}
first = false;
- element.toString(sb);
+ element.toString(sb, printType);
}
sb.append(' ');
}
diff --git a/src/jdk/nashorn/internal/ir/Optimistic.java b/src/jdk/nashorn/internal/ir/Optimistic.java
new file mode 100644
index 00000000..8337d087
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/Optimistic.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Is this a node that can be optimistically typed? This means that it
+ * has a probable type but it's not available through static analysis
+ *
+ * The follow nodes are optimistic, with reasons therefore given within
+ * parenthesis
+ *
+ * @see IndexNode (dynamicGetIndex)
+ * @see BinaryNode (local calculations to strongly typed bytecode)
+ * @see UnaryNode (local calculations to strongly typed bytecode)
+ * @see CallNode (dynamicCall)
+ * @see AccessNode (dynamicGet)
+ * @see IdentNode (dynamicGet)
+ */
+public interface Optimistic {
+ /**
+ * Unique node ID that is associated with an invokedynamic call that mail
+ * fail and its callsite. This is so that nodes can be regenerated less
+ * pessimistically the next generation if an assumption failed
+ *
+ * @return unique node id
+ */
+ public int getProgramPoint();
+
+ /**
+ * Set the node number for this node, associating with a unique per-function
+ * program point
+ * @param programPoint the node number
+ * @return new node, or same if unchanged
+ */
+ public Optimistic setProgramPoint(final int programPoint);
+
+ /**
+ * Is it possible for this particular implementor to actually have any optimism?
+ * SHIFT operators for instance are binary nodes, but never optimistic. Multiply
+ * operators are. We might want to refurbish the type hierarchy to fix this.
+ * @return true if theoretically optimistic
+ */
+ public boolean canBeOptimistic();
+
+ /**
+ * Get the most optimistic type for this node. Typically we start out as
+ * an int, and then at runtime we bump this up to number and then Object
+ *
+ * @return optimistic type to be used in code generation
+ */
+ public Type getMostOptimisticType();
+
+ /**
+ * Most pessimistic type that is guaranteed to be safe. Typically this is
+ * number for arithmetic operations that can overflow, or Object for an add
+ *
+ * @return pessimistic type guaranteed to never overflow
+ */
+ public Type getMostPessimisticType();
+
+ /**
+ * Set the override type
+ *
+ * @param type the type
+ * @return a node equivalent to this one except for the requested change.
+ */
+ public Optimistic setType(final Type type);
+}
diff --git a/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java b/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
new file mode 100644
index 00000000..9d97a438
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.ir;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.List;
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Lexical context that keeps track of optimistic assumptions (if any)
+ * made during code generation. Used from Attr and FinalizeTypes
+ */
+public class OptimisticLexicalContext extends LexicalContext {
+
+ private final boolean isEnabled;
+
+ class Assumption {
+ Symbol symbol;
+ Type type;
+
+ Assumption(final Symbol symbol, final Type type) {
+ this.symbol = symbol;
+ this.type = type;
+ }
+ @Override
+ public String toString() {
+ return symbol.getName() + "=" + type;
+ }
+ }
+
+ /** Optimistic assumptions that could be made per function */
+ private final Deque<List<Assumption>> optimisticAssumptions = new ArrayDeque<>();
+
+ /**
+ * Constructor
+ * @param isEnabled are optimistic types enabled?
+ */
+ public OptimisticLexicalContext(final boolean isEnabled) {
+ super();
+ this.isEnabled = isEnabled;
+ }
+
+ /**
+ * Are optimistic types enabled
+ * @return true if optimistic types
+ */
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ /**
+ * Log an optimistic assumption during codegen
+ * TODO : different parameters and more info about the assumption for future profiling
+ * needs
+ * @param symbol symbol
+ * @param type type
+ */
+ public void logOptimisticAssumption(final Symbol symbol, final Type type) {
+ if (isEnabled) {
+ final List<Assumption> peek = optimisticAssumptions.peek();
+ peek.add(new Assumption(symbol, type));
+ }
+ }
+
+ /**
+ * Get the list of optimistic assumptions made
+ * @return optimistic assumptions
+ */
+ public List<Assumption> getOptimisticAssumptions() {
+ return Collections.unmodifiableList(optimisticAssumptions.peek());
+ }
+
+ /**
+ * Does this method have optimistic assumptions made during codegen?
+ * @return true if optimistic assumptions were made
+ */
+ public boolean hasOptimisticAssumptions() {
+ return !optimisticAssumptions.isEmpty() && !getOptimisticAssumptions().isEmpty();
+ }
+
+ @Override
+ public <T extends LexicalContextNode> T push(final T node) {
+ if (isEnabled) {
+ if(node instanceof FunctionNode) {
+ optimisticAssumptions.push(new ArrayList<Assumption>());
+ }
+ }
+
+ return super.push(node);
+ }
+
+ @Override
+ public <T extends LexicalContextNode> T pop(final T node) {
+ final T popped = super.pop(node);
+ if (isEnabled) {
+ if(node instanceof FunctionNode) {
+ optimisticAssumptions.pop();
+ }
+ }
+ return popped;
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/ir/PropertyNode.java b/src/jdk/nashorn/internal/ir/PropertyNode.java
index 9cb82091..b9b8abea 100644
--- a/src/jdk/nashorn/internal/ir/PropertyNode.java
+++ b/src/jdk/nashorn/internal/ir/PropertyNode.java
@@ -33,6 +33,7 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class PropertyNode extends Node {
+ private static final long serialVersionUID = 1L;
/** Property key. */
private final PropertyKey key;
@@ -94,25 +95,25 @@ public final class PropertyNode extends Node {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
if (value instanceof FunctionNode && ((FunctionNode)value).getIdent() != null) {
value.toString(sb);
}
if (value != null) {
- ((Node)key).toString(sb);
+ ((Node)key).toString(sb, printType);
sb.append(": ");
- value.toString(sb);
+ value.toString(sb, printType);
}
if (getter != null) {
sb.append(' ');
- getter.toString(sb);
+ getter.toString(sb, printType);
}
if (setter != null) {
sb.append(' ');
- setter.toString(sb);
+ setter.toString(sb, printType);
}
}
diff --git a/src/jdk/nashorn/internal/ir/ReturnNode.java b/src/jdk/nashorn/internal/ir/ReturnNode.java
index 209e47b1..1491b834 100644
--- a/src/jdk/nashorn/internal/ir/ReturnNode.java
+++ b/src/jdk/nashorn/internal/ir/ReturnNode.java
@@ -36,6 +36,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public class ReturnNode extends Statement {
+ private static final long serialVersionUID = 1L;
+
/** Optional expression. */
private final Expression expression;
@@ -100,11 +102,11 @@ public class ReturnNode extends Statement {
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append(isYield() ? "yield" : "return");
if (expression != null) {
sb.append(' ');
- expression.toString(sb);
+ expression.toString(sb, printType);
}
}
diff --git a/src/jdk/nashorn/internal/ir/RuntimeNode.java b/src/jdk/nashorn/internal/ir/RuntimeNode.java
index 269cb905..4eca8ff0 100644
--- a/src/jdk/nashorn/internal/ir/RuntimeNode.java
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java
@@ -25,10 +25,12 @@
package jdk.nashorn.internal.ir;
-import java.util.ArrayList;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -38,7 +40,8 @@ import jdk.nashorn.internal.parser.TokenType;
* IR representation for a runtime call.
*/
@Immutable
-public class RuntimeNode extends Expression {
+public class RuntimeNode extends Expression implements Optimistic {
+ private static final long serialVersionUID = 1L;
/**
* Request enum used for meta-information about the runtime request
@@ -77,7 +80,11 @@ public class RuntimeNode extends Expression {
/** !== operator with at least one object */
NE_STRICT(TokenType.NE_STRICT, Type.BOOLEAN, 2, true),
/** != operator with at least one object */
- NE(TokenType.NE, Type.BOOLEAN, 2, true);
+ NE(TokenType.NE, Type.BOOLEAN, 2, true),
+ /** is undefined */
+ IS_UNDEFINED(TokenType.EQ_STRICT, Type.BOOLEAN, 2),
+ /** is not undefined */
+ IS_NOT_UNDEFINED(TokenType.NE_STRICT, Type.BOOLEAN, 2);
/** token type */
private final TokenType tokenType;
@@ -163,9 +170,14 @@ public class RuntimeNode extends Expression {
* @param node the node
* @return request type
*/
- public static Request requestFor(final Node node) {
- assert node.isComparison();
+ public static Request requestFor(final Expression node) {
switch (node.tokenType()) {
+ case TYPEOF:
+ return Request.TYPEOF;
+ case IN:
+ return Request.IN;
+ case INSTANCEOF:
+ return Request.INSTANCEOF;
case EQ_STRICT:
return Request.EQ_STRICT;
case NE_STRICT:
@@ -189,6 +201,17 @@ public class RuntimeNode extends Expression {
}
/**
+ * Is this an undefined check?
+ *
+ * @param request request
+ *
+ * @return true if undefined check
+ */
+ public static boolean isUndefinedCheck(final Request request) {
+ return request == IS_UNDEFINED || request == IS_NOT_UNDEFINED;
+ }
+
+ /**
* Is this an EQ or EQ_STRICT?
*
* @param request a request
@@ -211,6 +234,17 @@ public class RuntimeNode extends Expression {
}
/**
+ * Is this strict?
+ *
+ * @param request a request
+ *
+ * @return true if script
+ */
+ public static boolean isStrict(final Request request) {
+ return request == EQ_STRICT || request == NE_STRICT;
+ }
+
+ /**
* If this request can be reversed, return the reverse request
* Eq EQ {@literal ->} NE.
*
@@ -285,6 +319,8 @@ public class RuntimeNode extends Expression {
case LT:
case GE:
case GT:
+ case IS_UNDEFINED:
+ case IS_NOT_UNDEFINED:
return true;
default:
return false;
@@ -301,6 +337,8 @@ public class RuntimeNode extends Expression {
/** is final - i.e. may not be removed again, lower in the code pipeline */
private final boolean isFinal;
+ private final int programPoint;
+
/**
* Constructor
*
@@ -315,14 +353,16 @@ public class RuntimeNode extends Expression {
this.request = request;
this.args = args;
this.isFinal = false;
+ this.programPoint = INVALID_PROGRAM_POINT;
}
- private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args) {
+ private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args, final int programPoint) {
super(runtimeNode);
this.request = request;
this.args = args;
this.isFinal = isFinal;
+ this.programPoint = programPoint;
}
/**
@@ -361,6 +401,7 @@ public class RuntimeNode extends Expression {
this.request = request;
this.args = args;
this.isFinal = false;
+ this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT;
}
/**
@@ -370,20 +411,32 @@ public class RuntimeNode extends Expression {
* @param request the request
*/
public RuntimeNode(final UnaryNode parent, final Request request) {
- this(parent, request, parent.rhs());
+ this(parent, request, parent.getExpression());
}
/**
- * Constructor
+ * Constructor used to replace a binary node with a runtime request.
*
* @param parent parent node from which to inherit source, token, finish and arguments
- * @param request the request
*/
- public RuntimeNode(final BinaryNode parent, final Request request) {
- this(parent, request, parent.lhs(), parent.rhs());
+ public RuntimeNode(final BinaryNode parent) {
+ this(parent, Request.requestFor(parent), parent.lhs(), parent.rhs());
}
/**
+ * Reset the request for this runtime node
+ * @param request request
+ * @return new runtime node or same if same request
+ */
+ public RuntimeNode setRequest(final Request request) {
+ if (this.request == request) {
+ return this;
+ }
+ return new RuntimeNode(this, request, isFinal, args, programPoint);
+ }
+
+
+ /**
* Is this node final - i.e. it can never be replaced with other nodes again
* @return true if final
*/
@@ -400,32 +453,28 @@ public class RuntimeNode extends Expression {
if (this.isFinal == isFinal) {
return this;
}
- return new RuntimeNode(this, request, isFinal, args);
+ return new RuntimeNode(this, request, isFinal, args, programPoint);
}
/**
* Return type for the ReferenceNode
*/
@Override
- public Type getType() {
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
return request.getReturnType();
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterRuntimeNode(this)) {
- final List<Expression> newArgs = new ArrayList<>();
- for (final Node arg : args) {
- newArgs.add((Expression)arg.accept(visitor));
- }
- return visitor.leaveRuntimeNode(setArgs(newArgs));
+ return visitor.leaveRuntimeNode(setArgs(Node.accept(visitor, args)));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("ScriptRuntime.");
sb.append(request);
sb.append('(');
@@ -439,7 +488,7 @@ public class RuntimeNode extends Expression {
first = false;
}
- arg.toString(sb);
+ arg.toString(sb, printType);
}
sb.append(')');
@@ -453,11 +502,16 @@ public class RuntimeNode extends Expression {
return Collections.unmodifiableList(args);
}
- private RuntimeNode setArgs(final List<Expression> args) {
+ /**
+ * Set the arguments of this runtime node
+ * @param args new arguments
+ * @return new runtime node, or identical if no change
+ */
+ public RuntimeNode setArgs(final List<Expression> args) {
if (this.args == args) {
return this;
}
- return new RuntimeNode(this, request, isFinal, args);
+ return new RuntimeNode(this, request, isFinal, args, programPoint);
}
/**
@@ -483,4 +537,39 @@ public class RuntimeNode extends Expression {
}
return true;
}
+
+//TODO these are blank for now:
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ @Override
+ public RuntimeNode setProgramPoint(final int programPoint) {
+ if(this.programPoint == programPoint) {
+ return this;
+ }
+ return new RuntimeNode(this, request, isFinal, args, programPoint);
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return false;
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ return getType();
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return getType();
+ }
+
+ @Override
+ public RuntimeNode setType(final Type type) {
+ return this;
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/SetSplitState.java b/src/jdk/nashorn/internal/ir/SetSplitState.java
new file mode 100644
index 00000000..33ca3d15
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/SetSplitState.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Scope;
+
+/**
+ * Synthetic AST node that represents loading of the scope object and invocation of the {@link Scope#setSplitState(int)}
+ * method on it. It has no JavaScript source representation and only occurs in synthetic functions created by
+ * the split-into-functions transformation.
+ */
+public final class SetSplitState extends Statement {
+ private static final long serialVersionUID = 1L;
+
+ private final int state;
+
+ /**
+ * Creates a new split state setter
+ * @param state the state to set
+ * @param lineNumber the line number where it is inserted
+ */
+ public SetSplitState(final int state, final int lineNumber) {
+ super(lineNumber, NO_TOKEN, NO_FINISH);
+ this.state = state;
+ }
+
+ /**
+ * Returns the state this setter sets.
+ * @return the state this setter sets.
+ */
+ public int getState() {
+ return state;
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ return visitor.enterSetSplitState(this) ? visitor.leaveSetSplitState(this) : this;
+ }
+
+ @Override
+ public void toString(final StringBuilder sb, final boolean printType) {
+ sb.append(CompilerConstants.SCOPE.symbolName()).append('.').append(Scope.SET_SPLIT_STATE.name())
+ .append('(').append(state).append(");");
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/SplitNode.java b/src/jdk/nashorn/internal/ir/SplitNode.java
index d6c619b7..43b511d6 100644
--- a/src/jdk/nashorn/internal/ir/SplitNode.java
+++ b/src/jdk/nashorn/internal/ir/SplitNode.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.ir;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectOutputStream;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -33,7 +36,9 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* Node indicating code is split across classes.
*/
@Immutable
-public class SplitNode extends LexicalContextStatement {
+public class SplitNode extends LexicalContextStatement implements CompileUnitHolder {
+ private static final long serialVersionUID = 1L;
+
/** Split node method name. */
private final String name;
@@ -41,7 +46,7 @@ public class SplitNode extends LexicalContextStatement {
private final CompileUnit compileUnit;
/** Body of split code. */
- private final Node body;
+ private final Block body;
/**
* Constructor
@@ -50,49 +55,49 @@ public class SplitNode extends LexicalContextStatement {
* @param body body of split code
* @param compileUnit compile unit to use for the body
*/
- public SplitNode(final String name, final Node body, final CompileUnit compileUnit) {
- super(-1, body.getToken(), body.getFinish());
+ public SplitNode(final String name, final Block body, final CompileUnit compileUnit) {
+ super(body.getFirstStatementLineNumber(), body.getToken(), body.getFinish());
this.name = name;
this.body = body;
this.compileUnit = compileUnit;
}
- private SplitNode(final SplitNode splitNode, final Node body) {
+ private SplitNode(final SplitNode splitNode, final Block body, final CompileUnit compileUnit) {
super(splitNode);
this.name = splitNode.name;
this.body = body;
- this.compileUnit = splitNode.compileUnit;
+ this.compileUnit = compileUnit;
}
/**
* Get the body for this split node - i.e. the actual code it encloses
* @return body for split node
*/
- public Node getBody() {
+ public Block getBody() {
return body;
}
- private SplitNode setBody(final LexicalContext lc, final Node body) {
+ private SplitNode setBody(final LexicalContext lc, final Block body) {
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body));
+ return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit));
}
@Override
public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterSplitNode(this)) {
- return visitor.leaveSplitNode(setBody(lc, body.accept(visitor)));
+ return visitor.leaveSplitNode(setBody(lc, (Block)body.accept(visitor)));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("<split>(");
sb.append(compileUnit.getClass().getSimpleName());
sb.append(") ");
- body.toString(sb);
+ body.toString(sb, printType);
}
/**
@@ -107,8 +112,27 @@ public class SplitNode extends LexicalContextStatement {
* Get the compile unit for this split node
* @return compile unit
*/
+ @Override
public CompileUnit getCompileUnit() {
return compileUnit;
}
+ /**
+ * Set the compile unit for this split node
+ * @param lc lexical context
+ * @param compileUnit compile unit
+ * @return new node if changed, otherwise same node
+ */
+ public SplitNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
+ if (this.compileUnit == compileUnit) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit));
+ }
+
+ private void writeObject(final ObjectOutputStream out) throws IOException {
+ // We are only serializing the AST after we run SplitIntoFunctions; no SplitNodes can remain for the
+ // serialization.
+ throw new NotSerializableException(getClass().getName());
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/SplitReturn.java b/src/jdk/nashorn/internal/ir/SplitReturn.java
new file mode 100644
index 00000000..fb1b58c7
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/SplitReturn.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Synthetic AST node that represents return from a split fragment of a split function for control flow reasons (break
+ * or continue into a target outside the current fragment). It has no JavaScript source representation and only occurs
+ * in synthetic functions created by the split-into-functions transformation. It is different from a return node in
+ * that the return value is irrelevant, and doesn't affect the function's return type calculation.
+ */
+public final class SplitReturn extends Statement {
+ private static final long serialVersionUID = 1L;
+
+ /** The sole instance of this AST node. */
+ public static final SplitReturn INSTANCE = new SplitReturn();
+
+ private SplitReturn() {
+ super(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH);
+ }
+
+ @Override
+ public boolean isTerminal() {
+ return true;
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ return visitor.enterSplitReturn(this) ? visitor.leaveSplitReturn(this) : this;
+ }
+
+ @Override
+ public void toString(StringBuilder sb, boolean printType) {
+ sb.append(":splitreturn;");
+ }
+
+ private Object readResolve() {
+ return INSTANCE;
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/Statement.java b/src/jdk/nashorn/internal/ir/Statement.java
index 6b171cb9..f9a335c7 100644
--- a/src/jdk/nashorn/internal/ir/Statement.java
+++ b/src/jdk/nashorn/internal/ir/Statement.java
@@ -30,7 +30,8 @@ package jdk.nashorn.internal.ir;
* made up of statements. The only node subclass that needs to keep token and
* location information is the Statement
*/
-public abstract class Statement extends Node {
+public abstract class Statement extends Node implements Terminal {
+ private static final long serialVersionUID = 1L;
private final int lineNumber;
@@ -77,4 +78,32 @@ public abstract class Statement extends Node {
return lineNumber;
}
+ /**
+ * Is this a terminal statement, i.e. does it end control flow like a throw or return?
+ *
+ * @return true if this node statement is terminal
+ */
+ @Override
+ public boolean isTerminal() {
+ return false;
+ }
+
+ /**
+ * Check if this statement repositions control flow with goto like
+ * semantics, for example {@link BreakNode} or a {@link ForNode} with no test
+ * @return true if statement has goto semantics
+ */
+ public boolean hasGoto() {
+ return false;
+ }
+
+ /**
+ * Check if this statement has terminal flags, i.e. ends or breaks control flow
+ *
+ * @return true if has terminal flags
+ */
+ public final boolean hasTerminalFlags() {
+ return isTerminal() || hasGoto();
+ }
}
+
diff --git a/src/jdk/nashorn/internal/ir/SwitchNode.java b/src/jdk/nashorn/internal/ir/SwitchNode.java
index d31bec52..ca447587 100644
--- a/src/jdk/nashorn/internal/ir/SwitchNode.java
+++ b/src/jdk/nashorn/internal/ir/SwitchNode.java
@@ -37,6 +37,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class SwitchNode extends BreakableStatement {
+ private static final long serialVersionUID = 1L;
+
/** Switch expression. */
private final Expression expression;
@@ -46,6 +48,10 @@ public final class SwitchNode extends BreakableStatement {
/** Switch default index. */
private final int defaultCaseIndex;
+ /** True if all cases are 32-bit signed integer constants, without repetitions. It's a prerequisite for
+ * using a tableswitch/lookupswitch when generating code. */
+ private final boolean uniqueInteger;
+
/** Tag symbol. */
private Symbol tag;
@@ -64,23 +70,26 @@ public final class SwitchNode extends BreakableStatement {
this.expression = expression;
this.cases = cases;
this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
+ this.uniqueInteger = false;
}
- private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases, final int defaultCase) {
- super(switchNode);
+ private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
+ final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) {
+ super(switchNode, conversion);
this.expression = expression;
this.cases = cases;
- this.defaultCaseIndex = defaultCase;
- this.tag = switchNode.getTag(); //TODO are symbols inhereted as references?
+ this.defaultCaseIndex = defaultCaseIndex;
+ this.tag = switchNode.getTag(); //TODO are symbols inherited as references?
+ this.uniqueInteger = uniqueInteger;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
final List<CaseNode> newCases = new ArrayList<>();
for (final CaseNode caseNode : cases) {
- newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody()));
+ newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger));
}
@Override
@@ -103,16 +112,16 @@ public final class SwitchNode extends BreakableStatement {
if (visitor.enterSwitchNode(this)) {
return visitor.leaveSwitchNode(
setExpression(lc, (Expression)expression.accept(visitor)).
- setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
+ setCases(lc, Node.accept(visitor, cases), defaultCaseIndex));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("switch (");
- expression.toString(sb);
+ expression.toString(sb, printType);
sb.append(')');
}
@@ -138,7 +147,7 @@ public final class SwitchNode extends BreakableStatement {
* by NodeVisitors who perform operations on every case node
* @param lc lexical context
* @param cases list of cases
- * @return new switcy node or same if no state was changed
+ * @return new switch node or same if no state was changed
*/
public SwitchNode setCases(final LexicalContext lc, final List<CaseNode> cases) {
return setCases(lc, cases, defaultCaseIndex);
@@ -148,7 +157,7 @@ public final class SwitchNode extends BreakableStatement {
if (this.cases == cases) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
}
/**
@@ -180,7 +189,7 @@ public final class SwitchNode extends BreakableStatement {
if (this.expression == expression) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex));
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
}
/**
@@ -200,5 +209,32 @@ public final class SwitchNode extends BreakableStatement {
public void setTag(final Symbol tag) {
this.tag = tag;
}
-}
+ /**
+ * Returns true if all cases of this switch statement are 32-bit signed integer constants, without repetitions.
+ * @return true if all cases of this switch statement are 32-bit signed integer constants, without repetitions.
+ */
+ public boolean isUniqueInteger() {
+ return uniqueInteger;
+ }
+
+ /**
+ * Sets whether all cases of this switch statement are 32-bit signed integer constants, without repetitions.
+ * @param lc lexical context
+ * @param uniqueInteger if true, all cases of this switch statement have been determined to be 32-bit signed
+ * integer constants, without repetitions.
+ * @return this switch node, if the value didn't change, or a new switch node with the changed value
+ */
+ public SwitchNode setUniqueInteger(final LexicalContext lc, final boolean uniqueInteger) {
+ if(this.uniqueInteger == uniqueInteger) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ }
+
+ @Override
+ JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+ return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/ir/Symbol.java b/src/jdk/nashorn/internal/ir/Symbol.java
index 2906893f..d4ccd459 100644
--- a/src/jdk/nashorn/internal/ir/Symbol.java
+++ b/src/jdk/nashorn/internal/ir/Symbol.java
@@ -29,54 +29,62 @@ import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
-import jdk.nashorn.internal.codegen.types.Range;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.options.Options;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-
/**
- * Maps a name to specific data.
+ * Symbol is a symbolic address for a value ("variable" if you wish). Identifiers in JavaScript source, as well as
+ * certain synthetic variables created by the compiler are represented by Symbol objects. Symbols can address either
+ * local variable slots in bytecode ("slotted symbol"), or properties in scope objects ("scoped symbol"). A symbol can
+ * also end up being defined but then not used during symbol assignment calculations; such symbol will be neither
+ * scoped, nor slotted; it represents a dead variable (it might be written to, but is never read). Finally, a symbol can
+ * be both slotted and in scope. This special case can only occur with bytecode method parameters. They all come in as
+ * slotted, but if they are used by a nested function (or eval) then they will be copied into the scope object, and used
+ * from there onwards. Two further special cases are parameters stored in {@code NativeArguments} objects and parameters
+ * stored in {@code Object[]} parameter to variable-arity functions. Those use the {@code #getFieldIndex()} property to
+ * refer to their location.
*/
public final class Symbol implements Comparable<Symbol> {
- /** Symbol kinds. Kind ordered by precedence. */
- public static final int IS_TEMP = 1;
/** Is this Global */
- public static final int IS_GLOBAL = 2;
+ public static final int IS_GLOBAL = 1;
/** Is this a variable */
- public static final int IS_VAR = 3;
+ public static final int IS_VAR = 2;
/** Is this a parameter */
- public static final int IS_PARAM = 4;
- /** Is this a constant */
- public static final int IS_CONSTANT = 5;
+ public static final int IS_PARAM = 3;
/** Mask for kind flags */
- public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits
+ public static final int KINDMASK = (1 << 2) - 1; // Kinds are represented by lower two bits
- /** Is this scope */
- public static final int IS_SCOPE = 1 << 4;
+ /** Is this symbol in scope */
+ public static final int IS_SCOPE = 1 << 2;
/** Is this a this symbol */
- public static final int IS_THIS = 1 << 5;
- /** Can this symbol ever be undefined */
- public static final int CAN_BE_UNDEFINED = 1 << 6;
- /** Is this symbol always defined? */
- public static final int IS_ALWAYS_DEFINED = 1 << 8;
- /** Can this symbol ever have primitive types */
- public static final int CAN_BE_PRIMITIVE = 1 << 9;
+ public static final int IS_THIS = 1 << 3;
/** Is this a let */
- public static final int IS_LET = 1 << 10;
+ public static final int IS_LET = 1 << 4;
+ /** Is this a const */
+ public static final int IS_CONST = 1 << 5;
/** Is this an internal symbol, never represented explicitly in source code */
- public static final int IS_INTERNAL = 1 << 11;
+ public static final int IS_INTERNAL = 1 << 6;
/** Is this a function self-reference symbol */
- public static final int IS_FUNCTION_SELF = 1 << 12;
- /** Is this a specialized param? */
- public static final int IS_SPECIALIZED_PARAM = 1 << 13;
- /** Is this symbol a shared temporary? */
- public static final int IS_SHARED = 1 << 14;
+ public static final int IS_FUNCTION_SELF = 1 << 7;
/** Is this a function declaration? */
- public static final int IS_FUNCTION_DECLARATION = 1 << 15;
+ public static final int IS_FUNCTION_DECLARATION = 1 << 8;
+ /** Is this a program level symbol? */
+ public static final int IS_PROGRAM_LEVEL = 1 << 9;
+ /** Are this symbols' values stored in local variable slots? */
+ public static final int HAS_SLOT = 1 << 10;
+ /** Is this symbol known to store an int value ? */
+ public static final int HAS_INT_VALUE = 1 << 11;
+ /** Is this symbol known to store a long value ? */
+ public static final int HAS_LONG_VALUE = 1 << 12;
+ /** Is this symbol known to store a double value ? */
+ public static final int HAS_DOUBLE_VALUE = 1 << 13;
+ /** Is this symbol known to store an object value ? */
+ public static final int HAS_OBJECT_VALUE = 1 << 14;
+ /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */
+ public static final int HAS_BEEN_DECLARED = 1 << 15;
/** Null or name identifying symbol. */
private final String name;
@@ -84,21 +92,16 @@ public final class Symbol implements Comparable<Symbol> {
/** Symbol flags. */
private int flags;
- /** Type of symbol. */
- private Type type;
-
- /** Local variable slot. -1 indicates external property. */
- private int slot;
+ /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable
+ * is not stored in local variable slots or it is not yet known. */
+ private int firstSlot = -1;
/** Field number in scope or property; array index in varargs when not using arguments object. */
- private int fieldIndex;
+ private int fieldIndex = -1;
/** Number of times this symbol is used in code */
private int useCount;
- /** Range for symbol */
- private Range range;
-
/** Debugging option - dump info and stack trace when symbols with given names are manipulated */
private static final Set<String> TRACE_SYMBOLS;
private static final Set<String> TRACE_SYMBOLS_STACKTRACE;
@@ -109,7 +112,7 @@ public final class Symbol implements Comparable<Symbol> {
if (stacktrace != null) {
trace = stacktrace; //stacktrace always implies trace as well
TRACE_SYMBOLS_STACKTRACE = new HashSet<>();
- for (StringTokenizer st = new StringTokenizer(stacktrace, ","); st.hasMoreTokens(); ) {
+ for (final StringTokenizer st = new StringTokenizer(stacktrace, ","); st.hasMoreTokens(); ) {
TRACE_SYMBOLS_STACKTRACE.add(st.nextToken());
}
} else {
@@ -119,7 +122,7 @@ public final class Symbol implements Comparable<Symbol> {
if (trace != null) {
TRACE_SYMBOLS = new HashSet<>();
- for (StringTokenizer st = new StringTokenizer(trace, ","); st.hasMoreTokens(); ) {
+ for (final StringTokenizer st = new StringTokenizer(trace, ","); st.hasMoreTokens(); ) {
TRACE_SYMBOLS.add(st.nextToken());
}
} else {
@@ -132,49 +135,13 @@ public final class Symbol implements Comparable<Symbol> {
*
* @param name name of symbol
* @param flags symbol flags
- * @param type type of this symbol
- * @param slot bytecode slot for this symbol
*/
- protected Symbol(final String name, final int flags, final Type type, final int slot) {
+ public Symbol(final String name, final int flags) {
this.name = name;
this.flags = flags;
- this.type = type;
- this.slot = slot;
- this.fieldIndex = -1;
- this.range = Range.createUnknownRange();
- trace("CREATE SYMBOL");
- }
-
- /**
- * Constructor
- *
- * @param name name of symbol
- * @param flags symbol flags
- */
- public Symbol(final String name, final int flags) {
- this(name, flags, Type.UNKNOWN, -1);
- }
-
- /**
- * Constructor
- *
- * @param name name of symbol
- * @param flags symbol flags
- * @param type type of this symbol
- */
- public Symbol(final String name, final int flags, final Type type) {
- this(name, flags, type, -1);
- }
-
- private Symbol(final Symbol base, final String name, final int flags) {
- this.flags = flags;
- this.name = name;
-
- this.fieldIndex = base.fieldIndex;
- this.slot = base.slot;
- this.type = base.type;
- this.useCount = base.useCount;
- this.range = base.range;
+ if(shouldTrace()) {
+ trace("CREATE SYMBOL " + name);
+ }
}
private static String align(final String string, final int max) {
@@ -188,74 +155,58 @@ public final class Symbol implements Comparable<Symbol> {
}
/**
- * Return the type for this symbol. Normally, if there is no type override,
- * this is where any type for any node is stored. If the node has a TypeOverride,
- * it may override this, e.g. when asking for a scoped field as a double
- *
- * @return symbol type
- */
- public final Type getSymbolType() {
- return type;
- }
-
- /**
* Debugging .
*
* @param stream Stream to print to.
*/
void print(final PrintWriter stream) {
- final String printName = align(name, 20);
- final String printType = align(type.toString(), 10);
- final String printSlot = align(slot == -1 ? "none" : "" + slot, 10);
- String printFlags = "";
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(align(name, 20)).
+ append(": ").
+ append(", ").
+ append(align(firstSlot == -1 ? "none" : "" + firstSlot, 10));
switch (flags & KINDMASK) {
- case IS_TEMP:
- printFlags = "temp " + printFlags;
- break;
case IS_GLOBAL:
- printFlags = "global " + printFlags;
+ sb.append(" global");
break;
case IS_VAR:
- printFlags = "var " + printFlags;
+ if (isConst()) {
+ sb.append(" const");
+ } else if (isLet()) {
+ sb.append(" let");
+ } else {
+ sb.append(" var");
+ }
break;
case IS_PARAM:
- printFlags = "param " + printFlags;
- break;
- case IS_CONSTANT:
- printFlags = "CONSTANT " + printFlags;
+ sb.append(" param");
break;
default:
break;
}
if (isScope()) {
- printFlags += "scope ";
+ sb.append(" scope");
}
if (isInternal()) {
- printFlags += "internal ";
- }
-
- if (isLet()) {
- printFlags += "let ";
+ sb.append(" internal");
}
if (isThis()) {
- printFlags += "this ";
+ sb.append(" this");
}
- if (!canBeUndefined()) {
- printFlags += "always_def ";
+ if (isProgramLevel()) {
+ sb.append(" program");
}
- if (canBePrimitive()) {
- printFlags += "can_be_prim ";
- }
+ sb.append('\n');
- stream.print(printName + ": " + printType + ", " + printSlot + ", " + printFlags);
- stream.println();
+ stream.print(sb.toString());
}
/**
@@ -272,9 +223,16 @@ public final class Symbol implements Comparable<Symbol> {
* Allocate a slot for this symbol.
*
* @param needsSlot True if symbol needs a slot.
+ * @return the symbol
*/
- public void setNeedsSlot(final boolean needsSlot) {
- setSlot(needsSlot ? 0 : -1);
+ public Symbol setNeedsSlot(final boolean needsSlot) {
+ if(needsSlot) {
+ assert !isScope();
+ flags |= HAS_SLOT;
+ } else {
+ flags &= ~HAS_SLOT;
+ }
+ return this;
}
/**
@@ -283,7 +241,14 @@ public final class Symbol implements Comparable<Symbol> {
* @return Number of slots.
*/
public int slotCount() {
- return type.isCategory2() ? 2 : 1;
+ return ((flags & HAS_INT_VALUE) == 0 ? 0 : 1) +
+ ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2) +
+ ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) +
+ ((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1);
+ }
+
+ private boolean isSlotted() {
+ return firstSlot != -1 && ((flags & HAS_SLOT) != 0);
}
@Override
@@ -291,17 +256,18 @@ public final class Symbol implements Comparable<Symbol> {
final StringBuilder sb = new StringBuilder();
sb.append(name).
- append(' ').
- append('(').
- append(getSymbolType().getTypeClass().getSimpleName()).
- append(')');
+ append(' ');
if (hasSlot()) {
sb.append(' ').
append('(').
append("slot=").
- append(slot).
- append(')');
+ append(firstSlot).append(' ');
+ if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); }
+ if((flags & HAS_LONG_VALUE) != 0) { sb.append('J'); }
+ if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); }
+ if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); }
+ sb.append(')');
}
if (isScope()) {
@@ -312,10 +278,6 @@ public final class Symbol implements Comparable<Symbol> {
}
}
- if (canBePrimitive()) {
- sb.append(" P?");
- }
-
return sb.toString();
}
@@ -325,21 +287,31 @@ public final class Symbol implements Comparable<Symbol> {
}
/**
- * Does this symbol have an allocated bytecode slot. If not, it is scope
- * and must be loaded from memory upon access
+ * Does this symbol have an allocated bytecode slot? Note that having an allocated bytecode slot doesn't necessarily
+ * mean the symbol's value will be stored in it. Namely, a function parameter can have a bytecode slot, but if it is
+ * in scope, then the bytecode slot will not be used. See {@link #isBytecodeLocal()}.
*
* @return true if this symbol has a local bytecode slot
*/
public boolean hasSlot() {
- return slot >= 0;
+ return (flags & HAS_SLOT) != 0;
}
/**
- * Check if this is a temporary symbol
- * @return true if temporary
+ * Is this symbol a local variable stored in bytecode local variable slots? This is true for a slotted variable that
+ * is not in scope. (E.g. a parameter that is in scope is slotted, but it will not be a local variable).
+ * @return true if this symbol is using bytecode local slots for its storage.
*/
- public boolean isTemp() {
- return (flags & KINDMASK) == IS_TEMP;
+ public boolean isBytecodeLocal() {
+ return hasSlot() && !isScope();
+ }
+
+ /**
+ * Returns true if this symbol is dead (it is a local variable that is statically proven to never be read in any type).
+ * @return true if this symbol is dead
+ */
+ public boolean isDead() {
+ return (flags & (HAS_SLOT | IS_SCOPE)) == 0;
}
/**
@@ -349,16 +321,8 @@ public final class Symbol implements Comparable<Symbol> {
* @return true if this is scoped
*/
public boolean isScope() {
- assert ((flags & KINDMASK) != IS_GLOBAL) || ((flags & IS_SCOPE) == IS_SCOPE) : "global without scope flag";
- return (flags & IS_SCOPE) == IS_SCOPE;
- }
-
- /**
- * Returns true if this symbol is a temporary that is being shared across expressions.
- * @return true if this symbol is a temporary that is being shared across expressions.
- */
- public boolean isShared() {
- return (flags & IS_SHARED) == IS_SHARED;
+ assert (flags & KINDMASK) != IS_GLOBAL || (flags & IS_SCOPE) == IS_SCOPE : "global without scope flag";
+ return (flags & IS_SCOPE) != 0;
}
/**
@@ -366,51 +330,34 @@ public final class Symbol implements Comparable<Symbol> {
* @return true if a function declaration
*/
public boolean isFunctionDeclaration() {
- return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
- }
-
- /**
- * Creates an unshared copy of a symbol. The symbol must be currently shared.
- * @param newName the name for the new symbol.
- * @return a new, unshared symbol.
- */
- public Symbol createUnshared(final String newName) {
- assert isShared();
- return new Symbol(this, newName, flags & ~IS_SHARED);
+ return (flags & IS_FUNCTION_DECLARATION) != 0;
}
/**
* Flag this symbol as scope as described in {@link Symbol#isScope()}
+ * @return the symbol
*/
- /**
- * Flag this symbol as scope as described in {@link Symbol#isScope()}
- */
- public void setIsScope() {
+ public Symbol setIsScope() {
if (!isScope()) {
- trace("SET IS SCOPE");
- assert !isShared();
+ if(shouldTrace()) {
+ trace("SET IS SCOPE");
+ }
flags |= IS_SCOPE;
+ if(!isParam()) {
+ flags &= ~HAS_SLOT;
+ }
}
+ return this;
}
- /**
- * Mark this symbol as one being shared by multiple expressions. The symbol must be a temporary.
- */
- public void setIsShared() {
- if (!isShared()) {
- assert isTemp();
- trace("SET IS SHARED");
- flags |= IS_SHARED;
- }
- }
-
-
/**
* Mark this symbol as a function declaration.
*/
public void setIsFunctionDeclaration() {
if (!isFunctionDeclaration()) {
- trace("SET IS FUNCTION DECLARATION");
+ if(shouldTrace()) {
+ trace("SET IS FUNCTION DECLARATION");
+ }
flags |= IS_FUNCTION_DECLARATION;
}
}
@@ -440,92 +387,19 @@ public final class Symbol implements Comparable<Symbol> {
}
/**
- * Check if this symbol is always defined, which overrides all canBeUndefined tags
- * @return true if always defined
- */
- public boolean isAlwaysDefined() {
- return isParam() || (flags & IS_ALWAYS_DEFINED) == IS_ALWAYS_DEFINED;
- }
-
- /**
- * Get the range for this symbol
- * @return range for symbol
- */
- public Range getRange() {
- return range;
- }
-
- /**
- * Set the range for this symbol
- * @param range range
- */
- public void setRange(final Range range) {
- this.range = range;
- }
-
- /**
- * Check if this symbol represents a return value with a known non-generic type.
- * @return true if specialized return value
+ * Check if this is a program (script) level definition
+ * @return true if program level
*/
- public boolean isNonGenericReturn() {
- return getName().equals(RETURN.symbolName()) && type != Type.OBJECT;
- }
-
- /**
- * Check if this symbol is a function parameter of known
- * narrowest type
- * @return true if parameter
- */
- public boolean isSpecializedParam() {
- return (flags & IS_SPECIALIZED_PARAM) == IS_SPECIALIZED_PARAM;
- }
-
- /**
- * Check whether this symbol ever has primitive assignments. Conservative
- * @return true if primitive assignments exist
- */
- public boolean canBePrimitive() {
- return (flags & CAN_BE_PRIMITIVE) == CAN_BE_PRIMITIVE;
- }
-
- /**
- * Check if this symbol can ever be undefined
- * @return true if can be undefined
- */
- public boolean canBeUndefined() {
- return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED;
- }
-
- /**
- * Flag this symbol as potentially undefined in parts of the program
- */
- public void setCanBeUndefined() {
- assert type.isObject() : type;
- if (isAlwaysDefined()) {
- return;
- } else if (!canBeUndefined()) {
- assert !isShared();
- flags |= CAN_BE_UNDEFINED;
- }
- }
-
- /**
- * Flag this symbol as potentially primitive
- * @param type the primitive type it occurs with, currently unused but can be used for width guesses
- */
- public void setCanBePrimitive(final Type type) {
- if(!canBePrimitive()) {
- assert !isShared();
- flags |= CAN_BE_PRIMITIVE;
- }
+ public boolean isProgramLevel() {
+ return (flags & IS_PROGRAM_LEVEL) != 0;
}
/**
* Check if this symbol is a constant
* @return true if a constant
*/
- public boolean isConstant() {
- return (flags & KINDMASK) == IS_CONSTANT;
+ public boolean isConst() {
+ return (flags & IS_CONST) != 0;
}
/**
@@ -550,25 +424,40 @@ public final class Symbol implements Comparable<Symbol> {
* @return true if let
*/
public boolean isLet() {
- return (flags & IS_LET) == IS_LET;
+ return (flags & IS_LET) != 0;
}
/**
- * Flag this symbol as a let
+ * Flag this symbol as a function's self-referencing symbol.
+ * @return true if this symbol as a function's self-referencing symbol.
*/
- public void setIsLet() {
- if(!isLet()) {
- assert !isShared();
- flags |= IS_LET;
- }
+ public boolean isFunctionSelf() {
+ return (flags & IS_FUNCTION_SELF) != 0;
}
/**
- * Flag this symbol as a function's self-referencing symbol.
- * @return true if this symbol as a function's self-referencing symbol.
+ * Is this a block scoped symbol
+ * @return true if block scoped
*/
- public boolean isFunctionSelf() {
- return (flags & IS_FUNCTION_SELF) == IS_FUNCTION_SELF;
+ public boolean isBlockScoped() {
+ return isLet() || isConst();
+ }
+
+ /**
+ * Has this symbol been declared
+ * @return true if declared
+ */
+ public boolean hasBeenDeclared() {
+ return (flags & HAS_BEEN_DECLARED) != 0;
+ }
+
+ /**
+ * Mark this symbol as declared
+ */
+ public void setHasBeenDeclared() {
+ if (!hasBeenDeclared()) {
+ flags |= HAS_BEEN_DECLARED;
+ }
}
/**
@@ -587,12 +476,13 @@ public final class Symbol implements Comparable<Symbol> {
* and get allocated in a JO-prefixed ScriptObject subclass.
*
* @param fieldIndex field index - a positive integer
+ * @return the symbol
*/
- public void setFieldIndex(final int fieldIndex) {
- if(this.fieldIndex != fieldIndex) {
- assert !isShared();
+ public Symbol setFieldIndex(final int fieldIndex) {
+ if (this.fieldIndex != fieldIndex) {
this.fieldIndex = fieldIndex;
}
+ return this;
}
/**
@@ -606,117 +496,146 @@ public final class Symbol implements Comparable<Symbol> {
/**
* Set the symbol flags
* @param flags flags
+ * @return the symbol
*/
- public void setFlags(final int flags) {
- if(this.flags != flags) {
- assert !isShared();
+ public Symbol setFlags(final int flags) {
+ if (this.flags != flags) {
this.flags = flags;
}
+ return this;
}
/**
- * Get the name of this symbol
- * @return symbol name
+ * Set a single symbol flag
+ * @param flag flag to set
+ * @return the symbol
*/
- public String getName() {
- return name;
+ public Symbol setFlag(final int flag) {
+ if ((this.flags & flag) == 0) {
+ this.flags |= flag;
+ }
+ return this;
}
/**
- * Get the byte code slot for this symbol
- * @return byte code slot, or -1 if no slot allocated/possible
+ * Clears a single symbol flag
+ * @param flag flag to set
+ * @return the symbol
*/
- public int getSlot() {
- return slot;
+ public Symbol clearFlag(final int flag) {
+ if ((this.flags & flag) != 0) {
+ this.flags &= ~flag;
+ }
+ return this;
}
/**
- * Increase the symbol's use count by one.
+ * Get the name of this symbol
+ * @return symbol name
*/
- public void increaseUseCount() {
- useCount++;
+ public String getName() {
+ return name;
}
/**
- * Get the symbol's use count
- * @return the number of times the symbol is used in code.
+ * Get the index of the first bytecode slot for this symbol
+ * @return byte code slot
*/
- public int getUseCount() {
- return useCount;
+ public int getFirstSlot() {
+ assert isSlotted();
+ return firstSlot;
}
/**
- * Set the bytecode slot for this symbol
- * @param slot valid bytecode slot, or -1 if not available
+ * Get the index of the bytecode slot for this symbol for storing a value of the specified type.
+ * @param type the requested type
+ * @return byte code slot
*/
- public void setSlot(final int slot) {
- if (slot != this.slot) {
- assert !isShared();
- trace("SET SLOT " + slot);
- this.slot = slot;
+ public int getSlot(final Type type) {
+ assert isSlotted();
+ int typeSlot = firstSlot;
+ if(type.isBoolean() || type.isInteger()) {
+ assert (flags & HAS_INT_VALUE) != 0;
+ return typeSlot;
+ }
+ typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1);
+ if(type.isLong()) {
+ assert (flags & HAS_LONG_VALUE) != 0;
+ return typeSlot;
+ }
+ typeSlot += ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2);
+ if(type.isNumber()) {
+ assert (flags & HAS_DOUBLE_VALUE) != 0;
+ return typeSlot;
}
+ assert type.isObject();
+ assert (flags & HAS_OBJECT_VALUE) != 0 : name;
+ return typeSlot + ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2);
}
/**
- * Assign a specific subclass of Object to the symbol
- *
- * @param type the type
- */
- public void setType(final Class<?> type) {
- assert !type.isPrimitive() && !Number.class.isAssignableFrom(type) : "Class<?> types can only be subclasses of object";
- setType(Type.typeFor(type));
+ * Returns true if this symbol has a local variable slot for storing a value of specific type.
+ * @param type the type
+ * @return true if this symbol has a local variable slot for storing a value of specific type.
+ */
+ public boolean hasSlotFor(final Type type) {
+ if(type.isBoolean() || type.isInteger()) {
+ return (flags & HAS_INT_VALUE) != 0;
+ } else if(type.isLong()) {
+ return (flags & HAS_LONG_VALUE) != 0;
+ } else if(type.isNumber()) {
+ return (flags & HAS_DOUBLE_VALUE) != 0;
+ }
+ assert type.isObject();
+ return (flags & HAS_OBJECT_VALUE) != 0;
}
/**
- * Assign a type to the symbol
- *
+ * Marks this symbol as having a local variable slot for storing a value of specific type.
* @param type the type
*/
- public void setType(final Type type) {
- setTypeOverride(Type.widest(this.type, type));
+ public void setHasSlotFor(final Type type) {
+ if(type.isBoolean() || type.isInteger()) {
+ setFlag(HAS_INT_VALUE);
+ } else if(type.isLong()) {
+ setFlag(HAS_LONG_VALUE);
+ } else if(type.isNumber()) {
+ setFlag(HAS_DOUBLE_VALUE);
+ } else {
+ assert type.isObject();
+ setFlag(HAS_OBJECT_VALUE);
+ }
}
/**
- * Returns true if calling {@link #setType(Type)} on this symbol would effectively change its type.
- * @param newType the new type to test for
- * @return true if setting this symbols type to a new value would effectively change its type.
+ * Increase the symbol's use count by one.
+ * @return the symbol
*/
- public boolean wouldChangeType(final Type newType) {
- return Type.widest(this.type, newType) != this.type;
+ public Symbol increaseUseCount() {
+ useCount++;
+ return this;
}
/**
- * Only use this if you know about an existing type
- * constraint - otherwise a type can only be
- * widened
- *
- * @param type the type
- */
- public void setTypeOverride(final Type type) {
- final Type old = this.type;
- if (old != type) {
- assert !isShared();
- trace("TYPE CHANGE: " + old + "=>" + type + " == " + type);
- this.type = type;
- }
+ * Get the symbol's use count
+ * @return the number of times the symbol is used in code.
+ */
+ public int getUseCount() {
+ return useCount;
}
/**
- * Sets the type of the symbol to the specified type. If the type would be changed, but this symbol is a shared
- * temporary, it will instead return a different temporary symbol of the requested type from the passed temporary
- * symbols. That way, it never mutates the type of a shared temporary.
- * @param type the new type for the symbol
- * @param ts a holder of temporary symbols
- * @return either this symbol, or a different symbol if this symbol is a shared temporary and it type would have to
- * be changed.
- */
- public Symbol setTypeOverrideShared(final Type type, final TemporarySymbols ts) {
- if(getSymbolType() != type) {
- if(isShared()) {
- assert !hasSlot();
- return ts.getTypedTemporarySymbol(type);
+ * Set the bytecode slot for this symbol
+ * @param firstSlot valid bytecode slot
+ * @return the symbol
+ */
+ public Symbol setFirstSlot(final int firstSlot) {
+ assert firstSlot >= 0 && firstSlot <= 65535;
+ if (firstSlot != this.firstSlot) {
+ if(shouldTrace()) {
+ trace("SET SLOT " + firstSlot);
}
- setTypeOverride(type);
+ this.firstSlot = firstSlot;
}
return this;
}
@@ -728,22 +647,26 @@ public final class Symbol implements Comparable<Symbol> {
* when flags need to be tagged, but block is in the
* middle of evaluation and cannot be modified.
*
- * @param lc lexical context
- * @param symbol symbol
+ * @param lc lexical context
+ * @param symbol symbol
+ * @return the symbol
*/
- public static void setSymbolIsScope(final LexicalContext lc, final Symbol symbol) {
+ public static Symbol setSymbolIsScope(final LexicalContext lc, final Symbol symbol) {
symbol.setIsScope();
if (!symbol.isGlobal()) {
lc.setBlockNeedsScope(lc.getDefiningBlock(symbol));
}
+ return symbol;
+ }
+
+ private boolean shouldTrace() {
+ return TRACE_SYMBOLS != null && (TRACE_SYMBOLS.isEmpty() || TRACE_SYMBOLS.contains(name));
}
private void trace(final String desc) {
- if (TRACE_SYMBOLS != null && (TRACE_SYMBOLS.isEmpty() || TRACE_SYMBOLS.contains(name))) {
- Context.err(Debug.id(this) + " SYMBOL: '" + name + "' " + desc);
- if (TRACE_SYMBOLS_STACKTRACE != null && (TRACE_SYMBOLS_STACKTRACE.isEmpty() || TRACE_SYMBOLS_STACKTRACE.contains(name))) {
- new Throwable().printStackTrace(Context.getCurrentErr());
- }
+ Context.err(Debug.id(this) + " SYMBOL: '" + name + "' " + desc);
+ if (TRACE_SYMBOLS_STACKTRACE != null && (TRACE_SYMBOLS_STACKTRACE.isEmpty() || TRACE_SYMBOLS_STACKTRACE.contains(name))) {
+ new Throwable().printStackTrace(Context.getCurrentErr());
}
}
}
diff --git a/src/jdk/nashorn/internal/ir/TemporarySymbols.java b/src/jdk/nashorn/internal/ir/TemporarySymbols.java
deleted file mode 100644
index 4a438ddd..00000000
--- a/src/jdk/nashorn/internal/ir/TemporarySymbols.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.ir;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.TEMP_PREFIX;
-import static jdk.nashorn.internal.ir.Symbol.IS_TEMP;
-
-import java.util.HashMap;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Type;
-
-/**
- * Class that holds reusable temporary symbols by type.
- *
- */
-public class TemporarySymbols {
- private static final String prefix = TEMP_PREFIX.symbolName() + "$";
-
- private int totalSymbolCount;
- private final Map<Type, TypedTemporarySymbols> temporarySymbolsByType = new HashMap<>();
-
- /**
- * Associates a temporary symbol of a given type with a node, if the node doesn't already have any symbol.
- * @param lc the current lexical context
- * @param type the type of the temporary symbol
- * @param node the node
- * @return the node that is guaranteed to have a symbol.
- */
- public Expression ensureSymbol(final LexicalContext lc, final Type type, final Expression node) {
- final Symbol symbol = node.getSymbol();
- if (symbol != null) {
- return node;
- }
- return node.setSymbol(lc, getTypedTemporarySymbol(type));
- }
-
- /**
- * Given a type, returns a temporary symbol of that type.
- * @param type the required type of the symbol.
- * @return a temporary symbol of the required type.
- */
- public Symbol getTypedTemporarySymbol(final Type type) {
- return getTypedTemporarySymbols(type).getTemporarySymbol(type);
- }
-
- private TypedTemporarySymbols getTypedTemporarySymbols(final Type type) {
- TypedTemporarySymbols temporarySymbols = temporarySymbolsByType.get(type);
- if(temporarySymbols == null) {
- temporarySymbols = new TypedTemporarySymbols();
- temporarySymbolsByType.put(type, temporarySymbols);
- }
- return temporarySymbols;
- }
-
- /**
- * This method is called to signal to this object that all the symbols it holds can be reused now.
- */
- public void reuse() {
- for(TypedTemporarySymbols ts: temporarySymbolsByType.values()) {
- ts.reuse();
- }
- }
-
- /**
- * Given a shared symbol, creates an unshared copy of it with a unique name.
- * @param symbol the shared symbol
- * @return the unshared, uniquely named copy of the symbol
- */
- public Symbol createUnshared(Symbol symbol) {
- return symbol.createUnshared(getUniqueName());
- }
-
- private String getUniqueName() {
- return prefix + (++totalSymbolCount);
- }
-
- /**
- * Returns the total number of symbols this object created during its lifetime.
- * @return the total number of symbols this object created during its lifetime.
- */
- public int getTotalSymbolCount() {
- return totalSymbolCount;
- }
-
- private class TypedTemporarySymbols {
- private Symbol[] symbols = new Symbol[16];
- private int nextFreeSymbol = 0;
- private int symbolCount = 0;
-
- Symbol getTemporarySymbol(final Type type) {
- while(nextFreeSymbol < symbolCount) {
- final Symbol nextSymbol = symbols[nextFreeSymbol];
- assert nextSymbol != null;
- // If it has a slot, we can't reuse it.
- if(!nextSymbol.hasSlot()) {
- final Type symbolType = nextSymbol.getSymbolType();
- if(symbolType == type) {
- assert nextSymbol.isTemp();
- assert !nextSymbol.isScope();
- // If types match, we can reuse it.
- nextSymbol.setIsShared();
- nextFreeSymbol++;
- return nextSymbol;
- }
- // If its type changed, but it doesn't have a slot then move it to its new home according to its
- // new type.
- getTypedTemporarySymbols(symbolType).addSymbol(nextSymbol);
- }
- // If we can move another symbol into its place, do that and repeat the analysis for this symbol.
- --symbolCount;
- if(symbolCount != nextFreeSymbol) {
- final Symbol lastFreeSymbol = symbols[symbolCount];
- symbols[nextFreeSymbol] = lastFreeSymbol;
- }
- symbols[symbolCount] = null;
- }
- return createNewSymbol(type);
- }
-
- private Symbol createNewSymbol(final Type type) {
- ensureCapacity();
- final Symbol symbol = symbols[nextFreeSymbol] = new Symbol(getUniqueName(), IS_TEMP, type);
- nextFreeSymbol++;
- symbolCount++;
- return symbol;
- }
-
- private void addSymbol(Symbol symbol) {
- ensureCapacity();
- symbols[symbolCount++] = symbol;
- }
-
- void reuse() {
- nextFreeSymbol = 0;
- }
-
- private void ensureCapacity() {
- if(symbolCount == symbols.length) {
- final Symbol[] newSymbols = new Symbol[symbolCount * 2];
- System.arraycopy(symbols, 0, newSymbols, 0, symbolCount);
- symbols = newSymbols;
- }
- }
- }
-
-}
diff --git a/src/jdk/nashorn/internal/ir/Terminal.java b/src/jdk/nashorn/internal/ir/Terminal.java
new file mode 100644
index 00000000..3f5c25bc
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/Terminal.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+/**
+ * Interface for AST nodes that can have a flag determining if they can terminate function control flow.
+ */
+public interface Terminal {
+ /**
+ * Returns true if this AST node is (or contains) a statement that terminates function control flow.
+ * @return true if this AST node is (or contains) a statement that terminates function control flow.
+ */
+ public boolean isTerminal();
+}
diff --git a/src/jdk/nashorn/internal/ir/TernaryNode.java b/src/jdk/nashorn/internal/ir/TernaryNode.java
index 26c14b76..913262d9 100644
--- a/src/jdk/nashorn/internal/ir/TernaryNode.java
+++ b/src/jdk/nashorn/internal/ir/TernaryNode.java
@@ -25,20 +25,23 @@
package jdk.nashorn.internal.ir;
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
/**
- * TernaryNode nodes represent three operand operations (?:).
+ * TernaryNode represent the ternary operator {@code ?:}. Note that for control-flow calculation reasons its branch
+ * expressions (but not its test expression) are always wrapped in instances of {@link JoinPredecessorExpression}.
*/
@Immutable
public final class TernaryNode extends Expression {
- private final Expression test;
-
- private final Expression trueExpr;
+ private static final long serialVersionUID = 1L;
- /** Third argument. */
- private final Expression falseExpr;
+ private final Expression test;
+ private final JoinPredecessorExpression trueExpr;
+ private final JoinPredecessorExpression falseExpr;
/**
* Constructor
@@ -48,14 +51,15 @@ public final class TernaryNode extends Expression {
* @param trueExpr expression evaluated when test evaluates to true
* @param falseExpr expression evaluated when test evaluates to true
*/
- public TernaryNode(final long token, final Expression test, final Expression trueExpr, final Expression falseExpr) {
+ public TernaryNode(final long token, final Expression test, final JoinPredecessorExpression trueExpr, final JoinPredecessorExpression falseExpr) {
super(token, falseExpr.getFinish());
this.test = test;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
}
- private TernaryNode(final TernaryNode ternaryNode, final Expression test, final Expression trueExpr, final Expression falseExpr) {
+ private TernaryNode(final TernaryNode ternaryNode, final Expression test, final JoinPredecessorExpression trueExpr,
+ final JoinPredecessorExpression falseExpr) {
super(ternaryNode);
this.test = test;
this.trueExpr = trueExpr;
@@ -66,24 +70,25 @@ public final class TernaryNode extends Expression {
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterTernaryNode(this)) {
final Expression newTest = (Expression)getTest().accept(visitor);
- final Expression newTrueExpr = (Expression)getTrueExpression().accept(visitor);
- final Expression newFalseExpr = (Expression)falseExpr.accept(visitor);
- return visitor.leaveTernaryNode(setTest(newTest).setTrueExpression(newTrueExpr).setFalseExpression1(newFalseExpr));
+ final JoinPredecessorExpression newTrueExpr = (JoinPredecessorExpression)trueExpr.accept(visitor);
+ final JoinPredecessorExpression newFalseExpr = (JoinPredecessorExpression)falseExpr.accept(visitor);
+ return visitor.leaveTernaryNode(setTest(newTest).setTrueExpression(newTrueExpr).setFalseExpression(newFalseExpr));
}
return this;
}
@Override
- public void toString(final StringBuilder sb) {
- final boolean testParen = tokenType().needsParens(getTest().tokenType(), true);
- final boolean trueParen = tokenType().needsParens(getTrueExpression().tokenType(), false);
- final boolean falseParen = tokenType().needsParens(getFalseExpression().tokenType(), false);
+ public void toString(final StringBuilder sb, final boolean printType) {
+ final TokenType tokenType = tokenType();
+ final boolean testParen = tokenType.needsParens(getTest().tokenType(), true);
+ final boolean trueParen = tokenType.needsParens(getTrueExpression().tokenType(), false);
+ final boolean falseParen = tokenType.needsParens(getFalseExpression().tokenType(), false);
if (testParen) {
sb.append('(');
}
- getTest().toString(sb);
+ getTest().toString(sb, printType);
if (testParen) {
sb.append(')');
}
@@ -93,7 +98,7 @@ public final class TernaryNode extends Expression {
if (trueParen) {
sb.append('(');
}
- getTrueExpression().toString(sb);
+ getTrueExpression().toString(sb, printType);
if (trueParen) {
sb.append(')');
}
@@ -103,7 +108,7 @@ public final class TernaryNode extends Expression {
if (falseParen) {
sb.append('(');
}
- getFalseExpression().toString(sb);
+ getFalseExpression().toString(sb, printType);
if (falseParen) {
sb.append(')');
}
@@ -116,6 +121,12 @@ public final class TernaryNode extends Expression {
&& getFalseExpression().isLocal();
}
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ return Type.widestReturnType(getTrueExpression().getType(localVariableTypes), getFalseExpression().getType(localVariableTypes));
+ }
+
+
/**
* Get the test expression for this ternary expression, i.e. "x" in x ? y : z
* @return the test expression
@@ -128,7 +139,7 @@ public final class TernaryNode extends Expression {
* Get the true expression for this ternary expression, i.e. "y" in x ? y : z
* @return the true expression
*/
- public Expression getTrueExpression() {
+ public JoinPredecessorExpression getTrueExpression() {
return trueExpr;
}
@@ -136,7 +147,7 @@ public final class TernaryNode extends Expression {
* Get the false expression for this ternary expression, i.e. "z" in x ? y : z
* @return the false expression
*/
- public Expression getFalseExpression() {
+ public JoinPredecessorExpression getFalseExpression() {
return falseExpr;
}
@@ -157,7 +168,7 @@ public final class TernaryNode extends Expression {
* @param trueExpr new true expression
* @return a node equivalent to this one except for the requested change.
*/
- public TernaryNode setTrueExpression(final Expression trueExpr) {
+ public TernaryNode setTrueExpression(final JoinPredecessorExpression trueExpr) {
if (this.trueExpr == trueExpr) {
return this;
}
@@ -169,7 +180,7 @@ public final class TernaryNode extends Expression {
* @param falseExpr new false expression
* @return a node equivalent to this one except for the requested change.
*/
- public TernaryNode setFalseExpression1(final Expression falseExpr) {
+ public TernaryNode setFalseExpression(final JoinPredecessorExpression falseExpr) {
if (this.falseExpr == falseExpr) {
return this;
}
diff --git a/src/jdk/nashorn/internal/ir/ThrowNode.java b/src/jdk/nashorn/internal/ir/ThrowNode.java
index 70efa532..f422aea4 100644
--- a/src/jdk/nashorn/internal/ir/ThrowNode.java
+++ b/src/jdk/nashorn/internal/ir/ThrowNode.java
@@ -32,14 +32,15 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation for THROW statements.
*/
@Immutable
-public final class ThrowNode extends Statement {
+public final class ThrowNode extends Statement implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
/** Exception expression. */
private final Expression expression;
- private final int flags;
+ private final LocalVariableConversion conversion;
- /** Is this block a synthethic rethrow created by finally inlining? */
- public static final int IS_SYNTHETIC_RETHROW = 1;
+ private final boolean isSyntheticRethrow;
/**
* Constructor
@@ -48,18 +49,21 @@ public final class ThrowNode extends Statement {
* @param token token
* @param finish finish
* @param expression expression to throw
- * @param flags flags
+ * @param isSyntheticRethrow true if this throw node is part of a synthetic rethrow.
*/
- public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final int flags) {
+ public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow) {
super(lineNumber, token, finish);
this.expression = expression;
- this.flags = flags;
+ this.isSyntheticRethrow = isSyntheticRethrow;
+ this.conversion = null;
}
- private ThrowNode(final ThrowNode node, final Expression expression, final int flags) {
+ private ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow,
+ final LocalVariableConversion conversion) {
super(node);
this.expression = expression;
- this.flags = flags;
+ this.isSyntheticRethrow = isSyntheticRethrow;
+ this.conversion = conversion;
}
@Override
@@ -81,11 +85,14 @@ public final class ThrowNode extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("throw ");
if (expression != null) {
- expression.toString(sb);
+ expression.toString(sb, printType);
+ }
+ if (conversion != null) {
+ conversion.toString(sb);
}
}
@@ -106,7 +113,7 @@ public final class ThrowNode extends Statement {
if (this.expression == expression) {
return this;
}
- return new ThrowNode(this, expression, flags);
+ return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
}
/**
@@ -116,7 +123,20 @@ public final class ThrowNode extends Statement {
* @return true if synthetic throw node
*/
public boolean isSyntheticRethrow() {
- return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
+ return isSyntheticRethrow;
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
}
diff --git a/src/jdk/nashorn/internal/ir/TryNode.java b/src/jdk/nashorn/internal/ir/TryNode.java
index 6c30118e..605e0a9e 100644
--- a/src/jdk/nashorn/internal/ir/TryNode.java
+++ b/src/jdk/nashorn/internal/ir/TryNode.java
@@ -28,8 +28,6 @@ package jdk.nashorn.internal.ir;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-
-import jdk.nashorn.internal.codegen.Label;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -37,7 +35,9 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
* IR representation of a TRY statement.
*/
@Immutable
-public final class TryNode extends Statement {
+public final class TryNode extends Statement implements JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
/** Try statements. */
private final Block body;
@@ -47,15 +47,14 @@ public final class TryNode extends Statement {
/** Finally clause. */
private final Block finallyBody;
- /** Exit label. */
- private final Label exit;
-
/** Exception symbol. */
private Symbol exception;
/** Catchall exception for finally expansion, where applicable */
private Symbol finallyCatchAll;
+ private final LocalVariableConversion conversion;
+
/**
* Constructor
*
@@ -71,21 +70,22 @@ public final class TryNode extends Statement {
this.body = body;
this.catchBlocks = catchBlocks;
this.finallyBody = finallyBody;
- this.exit = new Label("exit");
+ this.conversion = null;
}
- private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody) {
+ private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion) {
super(tryNode);
this.body = body;
this.catchBlocks = catchBlocks;
this.finallyBody = finallyBody;
- this.exit = new Label(tryNode.exit);
+ this.conversion = conversion;
+ this.exception = tryNode.exception;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
//try nodes are never in lex context
- return new TryNode(this, body, catchBlocks, finallyBody);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion);
}
@Override
@@ -114,8 +114,7 @@ public final class TryNode extends Statement {
return visitor.leaveTryNode(
setBody(newBody).
setFinallyBody(newFinallyBody).
- setCatchBlocks(Node.accept(visitor, Block.class, catchBlocks)).
- setException(exception).
+ setCatchBlocks(Node.accept(visitor, catchBlocks)).
setFinallyCatchAll(finallyCatchAll));
}
@@ -123,7 +122,7 @@ public final class TryNode extends Statement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("try ");
}
@@ -144,7 +143,7 @@ public final class TryNode extends Statement {
if (this.body == body) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion);
}
/**
@@ -154,11 +153,15 @@ public final class TryNode extends Statement {
public List<CatchNode> getCatches() {
final List<CatchNode> catches = new ArrayList<>(catchBlocks.size());
for (final Block catchBlock : catchBlocks) {
- catches.add((CatchNode)catchBlock.getStatements().get(0));
+ catches.add(getCatchNodeFromBlock(catchBlock));
}
return Collections.unmodifiableList(catches);
}
+ private static CatchNode getCatchNodeFromBlock(final Block catchBlock) {
+ return (CatchNode)catchBlock.getStatements().get(0);
+ }
+
/**
* Get the catch blocks for this try block
* @return a list of blocks
@@ -176,7 +179,7 @@ public final class TryNode extends Statement {
if (this.catchBlocks == catchBlocks) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion);
}
/**
@@ -186,7 +189,6 @@ public final class TryNode extends Statement {
public Symbol getException() {
return exception;
}
-
/**
* Set the exception symbol for this try block
* @param exception a symbol for the compiler to store the exception in
@@ -219,14 +221,6 @@ public final class TryNode extends Statement {
}
/**
- * Get the exit label for this try block
- * @return exit label
- */
- public Label getExit() {
- return exit;
- }
-
- /**
* Get the body of the finally clause for this try
* @return finally body, or null if no finally
*/
@@ -243,6 +237,19 @@ public final class TryNode extends Statement {
if (this.finallyBody == finallyBody) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
}
diff --git a/src/jdk/nashorn/internal/ir/UnaryNode.java b/src/jdk/nashorn/internal/ir/UnaryNode.java
index 4923d31e..2cee33b6 100644
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java
+++ b/src/jdk/nashorn/internal/ir/UnaryNode.java
@@ -28,8 +28,14 @@ package jdk.nashorn.internal.ir;
import static jdk.nashorn.internal.parser.TokenType.BIT_NOT;
import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.Token;
@@ -39,9 +45,27 @@ import jdk.nashorn.internal.parser.TokenType;
* UnaryNode nodes represent single operand operations.
*/
@Immutable
-public final class UnaryNode extends Expression implements Assignment<Expression> {
+public final class UnaryNode extends Expression implements Assignment<Expression>, Optimistic {
+ private static final long serialVersionUID = 1L;
+
/** Right hand side argument. */
- private final Expression rhs;
+ private final Expression expression;
+
+ private final int programPoint;
+
+ private final Type type;
+
+ @Ignore
+ private static final List<TokenType> CAN_OVERFLOW =
+ Collections.unmodifiableList(
+ Arrays.asList(new TokenType[] {
+ TokenType.ADD,
+ TokenType.SUB, //negate
+ TokenType.DECPREFIX,
+ TokenType.DECPOSTFIX,
+ TokenType.INCPREFIX,
+ TokenType.INCPOSTFIX,
+ }));
/**
* Constructor
@@ -56,20 +80,24 @@ public final class UnaryNode extends Expression implements Assignment<Expression
/**
* Constructor
*
- * @param token token
- * @param start start
- * @param finish finish
- * @param rhs expression
+ * @param token token
+ * @param start start
+ * @param finish finish
+ * @param expression expression
*/
- public UnaryNode(final long token, final int start, final int finish, final Expression rhs) {
+ public UnaryNode(final long token, final int start, final int finish, final Expression expression) {
super(token, start, finish);
- this.rhs = rhs;
+ this.expression = expression;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.type = null;
}
- private UnaryNode(final UnaryNode unaryNode, final Expression rhs) {
+ private UnaryNode(final UnaryNode unaryNode, final Expression expression, final Type type, final int programPoint) {
super(unaryNode);
- this.rhs = rhs;
+ this.expression = expression;
+ this.programPoint = programPoint;
+ this.type = type;
}
/**
@@ -95,19 +123,53 @@ public final class UnaryNode extends Expression implements Assignment<Expression
return isAssignment();
}
+ private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+ @Override
+ public Type apply(final Symbol t) {
+ return null;
+ }
+ };
+
+
@Override
public Type getWidestOperationType() {
- return isAssignment() ? Type.NUMBER : Type.OBJECT;
+ return getWidestOperationType(UNKNOWN_LOCALS);
+ }
+
+ private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
+ switch (tokenType()) {
+ case ADD:
+ final Type operandType = getExpression().getType(localVariableTypes);
+ if(operandType == Type.BOOLEAN) {
+ return Type.INT;
+ } else if(operandType.isObject()) {
+ return Type.NUMBER;
+ }
+ assert operandType.isNumeric();
+ return operandType;
+ case SUB:
+ // This might seems overly conservative until you consider that -0 can only be represented as a double.
+ return Type.NUMBER;
+ case NOT:
+ case DELETE:
+ return Type.BOOLEAN;
+ case BIT_NOT:
+ return Type.INT;
+ case VOID:
+ return Type.UNDEFINED;
+ default:
+ return isAssignment() ? Type.NUMBER : Type.OBJECT;
+ }
}
@Override
public Expression getAssignmentDest() {
- return isAssignment() ? rhs() : null;
+ return isAssignment() ? getExpression() : null;
}
@Override
- public UnaryNode setAssignmentDest(Expression n) {
- return setRHS(n);
+ public UnaryNode setAssignmentDest(final Expression n) {
+ return setExpression(n);
}
@Override
@@ -122,7 +184,7 @@ public final class UnaryNode extends Expression implements Assignment<Expression
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterUnaryNode(this)) {
- return visitor.leaveUnaryNode(setRHS((Expression)rhs.accept(visitor)));
+ return visitor.leaveUnaryNode(setExpression((Expression)expression.accept(visitor)));
}
return this;
@@ -131,31 +193,33 @@ public final class UnaryNode extends Expression implements Assignment<Expression
@Override
public boolean isLocal() {
switch (tokenType()) {
- case NEW:
- return false;
- case ADD:
- case SUB:
- case NOT:
- case BIT_NOT:
- return rhs.isLocal() && rhs.getType().isJSPrimitive();
- case DECPOSTFIX:
- case DECPREFIX:
- case INCPOSTFIX:
- case INCPREFIX:
- return rhs instanceof IdentNode && rhs.isLocal() && rhs.getType().isJSPrimitive();
- default:
- return rhs.isLocal();
+ case NEW:
+ return false;
+ case ADD:
+ case SUB:
+ case NOT:
+ case BIT_NOT:
+ return expression.isLocal() && expression.getType().isJSPrimitive();
+ case DECPOSTFIX:
+ case DECPREFIX:
+ case INCPOSTFIX:
+ case INCPREFIX:
+ return expression instanceof IdentNode && expression.isLocal() && expression.getType().isJSPrimitive();
+ default:
+ return expression.isLocal();
}
}
@Override
- public void toString(final StringBuilder sb) {
- toString(sb, new Runnable() {
- @Override
- public void run() {
- sb.append(rhs().toString());
- }
- });
+ public void toString(final StringBuilder sb, final boolean printType) {
+ toString(sb,
+ new Runnable() {
+ @Override
+ public void run() {
+ getExpression().toString(sb, printType);
+ }
+ },
+ printType);
}
/**
@@ -163,23 +227,27 @@ public final class UnaryNode extends Expression implements Assignment<Expression
* operand to a specified runnable.
* @param sb the string builder to use
* @param rhsStringBuilder the runnable that appends the string representation of the operand to the string builder
+ * @param printType should we print type
* when invoked.
*/
- public void toString(final StringBuilder sb, final Runnable rhsStringBuilder) {
- final TokenType type = tokenType();
- final String name = type.getName();
- final boolean isPostfix = type == DECPOSTFIX || type == INCPOSTFIX;
+ public void toString(final StringBuilder sb, final Runnable rhsStringBuilder, final boolean printType) {
+ final TokenType tokenType = tokenType();
+ final String name = tokenType.getName();
+ final boolean isPostfix = tokenType == DECPOSTFIX || tokenType == INCPOSTFIX;
- boolean rhsParen = type.needsParens(rhs().tokenType(), false);
+ if (isOptimistic()) {
+ sb.append(Expression.OPT_IDENTIFIER);
+ }
+ boolean rhsParen = tokenType.needsParens(getExpression().tokenType(), false);
if (!isPostfix) {
if (name == null) {
- sb.append(type.name());
+ sb.append(tokenType.name());
rhsParen = true;
} else {
sb.append(name);
- if (type.ordinal() > BIT_NOT.ordinal()) {
+ if (tokenType.ordinal() > BIT_NOT.ordinal()) {
sb.append(' ');
}
}
@@ -194,7 +262,7 @@ public final class UnaryNode extends Expression implements Assignment<Expression
}
if (isPostfix) {
- sb.append(type == DECPOSTFIX ? "--" : "++");
+ sb.append(tokenType == DECPOSTFIX ? "--" : "++");
}
}
@@ -206,8 +274,8 @@ public final class UnaryNode extends Expression implements Assignment<Expression
*
* @return right hand side or expression node
*/
- public Expression rhs() {
- return rhs;
+ public Expression getExpression() {
+ return expression;
}
/**
@@ -216,13 +284,62 @@ public final class UnaryNode extends Expression implements Assignment<Expression
*
* @see BinaryNode
*
- * @param rhs right hand side or expression node
+ * @param expression right hand side or expression node
* @return a node equivalent to this one except for the requested change.
*/
- public UnaryNode setRHS(final Expression rhs) {
- if (this.rhs == rhs) {
+ public UnaryNode setExpression(final Expression expression) {
+ if (this.expression == expression) {
return this;
}
- return new UnaryNode(this, rhs);
+ return new UnaryNode(this, expression, type, programPoint);
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
}
+
+ @Override
+ public UnaryNode setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new UnaryNode(this, expression, type, programPoint);
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return getMostOptimisticType() != getMostPessimisticType();
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ if (CAN_OVERFLOW.contains(tokenType())) {
+ return Type.INT;
+ }
+ return getMostPessimisticType();
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return getWidestOperationType();
+ }
+
+ @Override
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ final Type widest = getWidestOperationType(localVariableTypes);
+ if(type == null) {
+ return widest;
+ }
+ return Type.narrowest(widest, Type.widest(type, expression.getType(localVariableTypes)));
+ }
+
+ @Override
+ public UnaryNode setType(final Type type) {
+ if (this.type == type) {
+ return this;
+ }
+ return new UnaryNode(this, expression, type, programPoint);
+ }
+
}
diff --git a/src/jdk/nashorn/internal/ir/VarNode.java b/src/jdk/nashorn/internal/ir/VarNode.java
index 67648a00..1cee8cb5 100644
--- a/src/jdk/nashorn/internal/ir/VarNode.java
+++ b/src/jdk/nashorn/internal/ir/VarNode.java
@@ -27,12 +27,15 @@ package jdk.nashorn.internal.ir;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
/**
* Node represents a var/let declaration.
*/
@Immutable
public final class VarNode extends Statement implements Assignment<IdentNode> {
+ private static final long serialVersionUID = 1L;
+
/** Var name. */
private final IdentNode name;
@@ -42,13 +45,16 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
/** Is this a var statement (as opposed to a "var" in a for loop statement) */
private final int flags;
- /** Flag that determines if this function node is a statement */
- public static final int IS_STATEMENT = 1 << 0;
+ /** Flag for ES6 LET declaration */
+ public static final int IS_LET = 1 << 0;
+
+ /** Flag for ES6 CONST declaration */
+ public static final int IS_CONST = 1 << 1;
/** Flag that determines if this is the last function declaration in a function
* This is used to micro optimize the placement of return value assignments for
* a program node */
- public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 1;
+ public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 2;
/**
* Constructor
@@ -60,7 +66,7 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
* @param init init node or null if just a declaration
*/
public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init) {
- this(lineNumber, token, finish, name, init, IS_STATEMENT);
+ this(lineNumber, token, finish, name, init, 0);
}
private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) {
@@ -99,7 +105,7 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
}
@Override
- public VarNode setAssignmentDest(IdentNode n) {
+ public VarNode setAssignmentDest(final IdentNode n) {
return setName(n);
}
@@ -109,6 +115,43 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
}
/**
+ * Is this a VAR node block scoped? This returns true for ECMAScript 6 LET and CONST nodes.
+ * @return true if an ES6 LET or CONST node
+ */
+ public boolean isBlockScoped() {
+ return getFlag(IS_LET) || getFlag(IS_CONST);
+ }
+
+ /**
+ * Is this an ECMAScript 6 LET node?
+ * @return true if LET node
+ */
+ public boolean isLet() {
+ return getFlag(IS_LET);
+ }
+
+ /**
+ * Is this an ECMAScript 6 CONST node?
+ * @return true if CONST node
+ */
+ public boolean isConst() {
+ return getFlag(IS_CONST);
+ }
+
+ /**
+ * Return the flags to use for symbols for this declaration.
+ * @return the symbol flags
+ */
+ public int getSymbolFlags() {
+ if (isLet()) {
+ return Symbol.IS_VAR | Symbol.IS_LET;
+ } else if (isConst()) {
+ return Symbol.IS_VAR | Symbol.IS_CONST;
+ }
+ return Symbol.IS_VAR;
+ }
+
+ /**
* Does this variable declaration have an init value
* @return true if an init exists, false otherwise
*/
@@ -123,8 +166,9 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterVarNode(this)) {
- final IdentNode newName = (IdentNode)name.accept(visitor);
+ // var is right associative, so visit init before name
final Expression newInit = init == null ? null : (Expression)init.accept(visitor);
+ final IdentNode newName = (IdentNode)name.accept(visitor);
final VarNode newThis;
if (name != newName || init != newInit) {
newThis = new VarNode(this, newName, newInit, flags);
@@ -137,13 +181,13 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
}
@Override
- public void toString(final StringBuilder sb) {
- sb.append("var ");
- name.toString(sb);
+ public void toString(final StringBuilder sb, final boolean printType) {
+ sb.append(Token.descType(getToken()).getName()).append(' ');
+ name.toString(sb, printType);
if (init != null) {
sb.append(" = ");
- init.toString(sb);
+ init.toString(sb, printType);
}
}
@@ -213,18 +257,18 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
}
/**
- * Returns true if this is a var statement (as opposed to a var initializer in a for loop).
- * @return true if this is a var statement (as opposed to a var initializer in a for loop).
- */
- public boolean isStatement() {
- return (flags & IS_STATEMENT) != 0;
- }
-
- /**
* Returns true if this is a function declaration.
* @return true if this is a function declaration.
*/
public boolean isFunctionDeclaration() {
return init instanceof FunctionNode && ((FunctionNode)init).isDeclared();
}
+
+ /**
+ * Returns true if this is an anonymous function declaration.
+ * @return true if this is an anonymous function declaration.
+ */
+ public boolean isAnonymousFunctionDeclaration() {
+ return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous();
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/WhileNode.java b/src/jdk/nashorn/internal/ir/WhileNode.java
index 97e7ca54..7e60fee0 100644
--- a/src/jdk/nashorn/internal/ir/WhileNode.java
+++ b/src/jdk/nashorn/internal/ir/WhileNode.java
@@ -34,6 +34,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class WhileNode extends LoopNode {
+ private static final long serialVersionUID = 1L;
+
/** is this a do while node ? */
private final boolean isDoWhile;
@@ -47,7 +49,7 @@ public final class WhileNode extends LoopNode {
* @param isDoWhile is this a do while loop?
*/
public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile) {
- super(lineNumber, token, finish, null, null, false);
+ super(lineNumber, token, finish, null, false);
this.isDoWhile = isDoWhile;
}
@@ -58,15 +60,16 @@ public final class WhileNode extends LoopNode {
* @param test test
* @param body body
* @param controlFlowEscapes control flow escapes?
+ * @param conversion TODO
*/
- protected WhileNode(final WhileNode whileNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
- super(whileNode, test, body, controlFlowEscapes);
+ private WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+ super(whileNode, test, body, controlFlowEscapes, conversion);
this.isDoWhile = whileNode.isDoWhile;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
- return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
}
@Override
@@ -80,26 +83,21 @@ public final class WhileNode extends LoopNode {
if (isDoWhile()) {
return visitor.leaveWhileNode(
setBody(lc, (Block)body.accept(visitor)).
- setTest(lc, (Expression)test.accept(visitor)));
+ setTest(lc, (JoinPredecessorExpression)test.accept(visitor)));
}
return visitor.leaveWhileNode(
- setTest(lc, (Expression)test.accept(visitor)).
+ setTest(lc, (JoinPredecessorExpression)test.accept(visitor)).
setBody(lc, (Block)body.accept(visitor)));
}
return this;
}
@Override
- public Expression getTest() {
- return test;
- }
-
- @Override
- public WhileNode setTest(final LexicalContext lc, final Expression test) {
+ public WhileNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
if (this.test == test) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
}
@Override
@@ -112,7 +110,7 @@ public final class WhileNode extends LoopNode {
if (this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
}
@Override
@@ -120,7 +118,12 @@ public final class WhileNode extends LoopNode {
if (this.controlFlowEscapes == controlFlowEscapes) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+ return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
+ }
+
+ @Override
+ JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+ return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
}
/**
@@ -132,9 +135,9 @@ public final class WhileNode extends LoopNode {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("while (");
- test.toString(sb);
+ test.toString(sb, printType);
sb.append(')');
}
@@ -145,4 +148,9 @@ public final class WhileNode extends LoopNode {
}
return test == null;
}
+
+ @Override
+ public boolean hasPerIterationScope() {
+ return false;
+ }
}
diff --git a/src/jdk/nashorn/internal/ir/WithNode.java b/src/jdk/nashorn/internal/ir/WithNode.java
index 69bd22d6..a9ef936a 100644
--- a/src/jdk/nashorn/internal/ir/WithNode.java
+++ b/src/jdk/nashorn/internal/ir/WithNode.java
@@ -33,6 +33,8 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor;
*/
@Immutable
public final class WithNode extends LexicalContextStatement {
+ private static final long serialVersionUID = 1L;
+
/** This expression. */
private final Expression expression;
@@ -79,9 +81,9 @@ public final class WithNode extends LexicalContextStatement {
}
@Override
- public void toString(final StringBuilder sb) {
+ public void toString(final StringBuilder sb, final boolean printType) {
sb.append("with (");
- expression.toString(sb);
+ expression.toString(sb, printType);
sb.append(')');
}
diff --git a/src/jdk/nashorn/internal/ir/debug/ASTWriter.java b/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
index 19e4d04f..52e3c0e0 100644
--- a/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
+++ b/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
@@ -36,8 +36,11 @@ import java.util.List;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.Terminal;
import jdk.nashorn.internal.ir.TernaryNode;
import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Reference;
@@ -104,23 +107,31 @@ public final class ASTWriter {
final boolean isReference = field != null && field.isAnnotationPresent(Reference.class);
- Class<?> clazz = node.getClass();
+ final Class<?> clazz = node.getClass();
String type = clazz.getName();
type = type.substring(type.lastIndexOf('.') + 1, type.length());
+ int truncate = type.indexOf("Node");
+ if (truncate == -1) {
+ truncate = type.indexOf("Statement");
+ }
+ if (truncate != -1) {
+ type = type.substring(0, truncate);
+ }
+ type = type.toLowerCase();
+
if (isReference) {
type = "ref: " + type;
}
- type += "@" + Debug.id(node);
final Symbol symbol;
- if(node instanceof Expression) {
- symbol = ((Expression)node).getSymbol();
+ if (node instanceof IdentNode) {
+ symbol = ((IdentNode)node).getSymbol();
} else {
symbol = null;
}
if (symbol != null) {
- type += "#" + symbol;
+ type += ">" + symbol;
}
if (node instanceof Block && ((Block)node).needsScope()) {
@@ -135,11 +146,11 @@ public final class ASTWriter {
String status = "";
- if (node.isTerminal()) {
+ if (node instanceof Terminal && ((Terminal)node).isTerminal()) {
status += " Terminal";
}
- if (node.hasGoto()) {
+ if (node instanceof Statement && ((Statement)node).hasGoto()) {
status += " Goto ";
}
@@ -160,6 +171,8 @@ public final class ASTWriter {
status += " (" + tname + ")";
}
+ status += " @" + Debug.id(node);
+
if (children.isEmpty()) {
sb.append("[").
append(type).
@@ -200,7 +213,7 @@ public final class ASTWriter {
} else if (value instanceof Collection) {
int pos = 0;
ASTWriter.indent(sb, indent + 1);
- sb.append("[Collection ").
+ sb.append('[').
append(child.getName()).
append("[0..").
append(((Collection<Node>)value).size()).
diff --git a/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java b/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
index c65f8ef7..d5c8174f 100644
--- a/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
+++ b/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
@@ -30,7 +30,7 @@ import java.util.Comparator;
/**
* Class histogram element for IR / Java object instrumentation
*/
-public class ClassHistogramElement {
+public final class ClassHistogramElement {
/**
* Instance comparator
*/
diff --git a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
index ef7f8a1b..e3916d69 100644
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
@@ -27,10 +27,9 @@ package jdk.nashorn.internal.ir.debug;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.ArrayList;
-import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
@@ -41,12 +40,14 @@ import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.EmptyNode;
+import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
@@ -72,7 +73,6 @@ import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ParserException;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.Source;
/**
@@ -83,17 +83,17 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
/**
* Returns AST as JSON compatible string.
*
- * @param env script environment to use
+ * @param context context
* @param code code to be parsed
* @param name name of the code source (used for location)
* @param includeLoc tells whether to include location information for nodes or not
* @return JSON string representation of AST of the supplied code
*/
- public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) {
- final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict);
+ public static String parse(final Context context, final String code, final String name, final boolean includeLoc) {
+ final Parser parser = new Parser(context.getEnv(), sourceFor(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class));
final JSONWriter jsonWriter = new JSONWriter(includeLoc);
try {
- final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName());
+ final FunctionNode functionNode = parser.parse(); //symbol name is ":program", default
functionNode.accept(jsonWriter);
return jsonWriter.getString();
} catch (final ParserException e) {
@@ -103,6 +103,17 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
}
@Override
+ public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinPredecessorExpression) {
+ final Expression expr = joinPredecessorExpression.getExpression();
+ if(expr != null) {
+ expr.accept(this);
+ } else {
+ nullValue();
+ }
+ return false;
+ }
+
+ @Override
protected boolean enterDefault(final Node node) {
objectStart();
location(node);
@@ -132,8 +143,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
accessNode.getBase().accept(this);
comma();
- property("property");
- accessNode.getProperty().accept(this);
+ property("property", accessNode.getProperty());
comma();
property("computed", false);
@@ -153,16 +163,6 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
return leave();
}
- private static boolean isLogical(final TokenType tt) {
- switch (tt) {
- case AND:
- case OR:
- return true;
- default:
- return false;
- }
- }
-
@Override
public boolean enterBinaryNode(final BinaryNode binaryNode) {
enterDefault(binaryNode);
@@ -170,7 +170,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
final String name;
if (binaryNode.isAssignment()) {
name = "AssignmentExpression";
- } else if (isLogical(binaryNode.tokenType())) {
+ } else if (binaryNode.isLogical()) {
name = "LogicalExpression";
} else {
name = "BinaryExpression";
@@ -199,11 +199,11 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
type("BreakStatement");
comma();
- final IdentNode label = breakNode.getLabel();
- property("label");
- if (label != null) {
- label.accept(this);
+ final String label = breakNode.getLabelName();
+ if(label != null) {
+ property("label", label);
} else {
+ property("label");
nullValue();
}
@@ -278,11 +278,11 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
type("ContinueStatement");
comma();
- final IdentNode label = continueNode.getLabel();
- property("label");
- if (label != null) {
- label.accept(this);
+ final String label = continueNode.getLabelName();
+ if(label != null) {
+ property("label", label);
} else {
+ property("label");
nullValue();
}
@@ -319,7 +319,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
}
@Override
- public boolean enterBlockStatement(BlockStatement blockStatement) {
+ public boolean enterBlockStatement(final BlockStatement blockStatement) {
enterDefault(blockStatement);
type("BlockStatement");
@@ -339,13 +339,13 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
type("ForInStatement");
comma();
- Node init = forNode.getInit();
+ final Node init = forNode.getInit();
assert init != null;
property("left");
init.accept(this);
comma();
- Node modify = forNode.getModify();
+ final Node modify = forNode.getModify();
assert modify != null;
property("right");
modify.accept(this);
@@ -535,8 +535,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
type("LabeledStatement");
comma();
- property("label");
- labelNode.getLabel().accept(this);
+ property("label", labelNode.getLabelName());
comma();
property("body");
@@ -762,8 +761,8 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
final List<CatchNode> guarded = new ArrayList<>();
CatchNode unguarded = null;
if (catches != null) {
- for (Node n : catches) {
- CatchNode cn = (CatchNode)n;
+ for (final Node n : catches) {
+ final CatchNode cn = (CatchNode)n;
if (cn.getExceptionCondition() != null) {
guarded.add(cn);
} else {
@@ -804,7 +803,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
type("NewExpression");
comma();
- final CallNode callNode = (CallNode)unaryNode.rhs();
+ final CallNode callNode = (CallNode)unaryNode.getExpression();
property("callee");
callNode.getFunction().accept(this);
comma();
@@ -846,7 +845,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
comma();
property("argument");
- unaryNode.rhs().accept(this);
+ unaryNode.getExpression().accept(this);
}
return leave();
@@ -959,9 +958,13 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
buf.append(key);
buf.append("\":");
if (value != null) {
- if (escape) buf.append('"');
+ if (escape) {
+ buf.append('"');
+ }
buf.append(value);
- if (escape) buf.append('"');
+ if (escape) {
+ buf.append('"');
+ }
}
}
diff --git a/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
new file mode 100644
index 00000000..87eb18df
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir.debug;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.nashorn.internal.ir.debug.NashornTextifier.NashornLabel;
+
+/**
+ * Subclass of the ASM classs reader that retains more info, such
+ * as bytecode offsets
+ */
+public class NashornClassReader extends ClassReader {
+
+ private final Map<String, List<Label>> labelMap = new HashMap<>();
+
+ /**
+ * Constructor
+ * @param bytecode bytecode for class
+ */
+ public NashornClassReader(final byte[] bytecode) {
+ super(bytecode);
+ parse(bytecode);
+ }
+
+ List<Label> getExtraLabels(final String className, final String methodName, final String methodDesc) {
+ final String key = fullyQualifiedName(className, methodName, methodDesc);
+ return labelMap.get(key);
+ }
+
+ private static int readByte(final byte[] bytecode, final int index) {
+ return (byte)(bytecode[index] & 0xff);
+ }
+
+ private static int readShort(final byte[] bytecode, final int index) {
+ return (short)((bytecode[index] & 0xff) << 8) | (bytecode[index + 1] & 0xff);
+ }
+
+ private static int readInt(final byte[] bytecode, final int index) {
+ return ((bytecode[index] & 0xff) << 24) | ((bytecode[index + 1] & 0xff) << 16) | ((bytecode[index + 2] & 0xff) << 8) | (bytecode[index + 3] & 0xff);
+ }
+
+ private static long readLong(final byte[] bytecode, final int index) {
+ final int hi = readInt(bytecode, index);
+ final int lo = readInt(bytecode, index + 4);
+ return ((long)hi << 32) | lo;
+ }
+
+ private static String readUTF(final int index, final int utfLen, final byte[] bytecode) {
+ final int endIndex = index + utfLen;
+ final char buf[] = new char[utfLen * 2];
+ int strLen = 0;
+ int c;
+ int st = 0;
+ char cc = 0;
+ int i = index;
+
+ while (i < endIndex) {
+ c = bytecode[i++];
+ switch (st) {
+ case 0:
+ c = c & 0xFF;
+ if (c < 0x80) { // 0xxxxxxx
+ buf[strLen++] = (char) c;
+ } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
+ cc = (char) (c & 0x1F);
+ st = 1;
+ } else { // 1110 xxxx 10xx xxxx 10xx xxxx
+ cc = (char) (c & 0x0F);
+ st = 2;
+ }
+ break;
+
+ case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
+ buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+ st = 0;
+ break;
+
+ case 2: // byte 2 of 3-byte char
+ cc = (char) ((cc << 6) | (c & 0x3F));
+ st = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return new String(buf, 0, strLen);
+ }
+
+ private String parse(final byte[] bytecode) {
+ String thisClassName;
+
+ int u = 0;
+
+ final int magic = readInt(bytecode, u);
+ u += 4; //magic
+ assert magic == 0xcafebabe : Integer.toHexString(magic);
+ readShort(bytecode, u); //minor
+ u += 2;
+ readShort(bytecode, u); //major
+ u += 2; //minor
+
+ final int cpc = readShort(bytecode, u);
+ u += 2;
+ final ArrayList<Constant> cp = new ArrayList<>(cpc);
+ cp.add(null);
+
+ for (int i = 1; i < cpc; i++) {
+ //constant pool entries
+ final int tag = readByte(bytecode, u);
+ u += 1;
+ switch (tag) {
+ case 7: //class
+ cp.add(new IndexInfo(cp, tag, readShort(bytecode, u)));
+ u += 2;
+ break;
+ case 9: //fieldref
+ case 10: //methodref
+ case 11: //interfacemethodref
+ cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)));
+ u += 4;
+ break;
+ case 8: //string
+ cp.add(new IndexInfo(cp, tag, readShort(bytecode, u))); //string index
+ u += 2;
+ break;
+ case 3: //int
+ cp.add(new DirectInfo<>(cp, tag, readInt(bytecode, u)));
+ u += 4;
+ break;
+ case 4: //float
+ cp.add(new DirectInfo<>(cp, tag, Float.intBitsToFloat(readInt(bytecode, u))));
+ u += 4;
+ break;
+ case 5: //long
+ cp.add(new DirectInfo<>(cp, tag, readLong(bytecode, u)));
+ cp.add(null);
+ i++;
+ u += 8;
+ break;
+ case 6: //double
+ cp.add(new DirectInfo<>(cp, tag, Double.longBitsToDouble(readLong(bytecode, u))));
+ cp.add(null);
+ i++;
+ u += 8;
+ break;
+ case 12: //name and type
+ cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)));
+ u += 4;
+ break;
+ case 1: //utf8
+ final int len = readShort(bytecode, u);
+ u += 2;
+ cp.add(new DirectInfo<>(cp, tag, readUTF(u, len, bytecode)));
+ u += len;
+ break;
+ case 16: //methodtype
+ cp.add(new IndexInfo(cp, tag, readShort(bytecode, u)));
+ u += 2;
+ break;
+ case 18: //indy
+ cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)) {
+ @Override
+ public String toString() {
+ return "#" + index + ' ' + cp.get(index2).toString();
+ }
+
+ });
+ u += 4;
+ break;
+ case 15: //methodhandle
+ final int kind = readByte(bytecode, u);
+ assert kind >= 1 && kind <= 9 : kind;
+ cp.add(new IndexInfo2(cp, tag, kind, readShort(bytecode, u + 1)) {
+ @Override
+ public String toString() {
+ return "#" + index + ' ' + cp.get(index2).toString();
+ }
+ });
+
+ u += 3;
+ break;
+ default:
+ assert false : tag;
+ break;
+ }
+ }
+
+ readShort(bytecode, u); //access flags
+ u += 2; //access
+ final int cls = readShort(bytecode, u);
+ u += 2; //this_class
+ thisClassName = cp.get(cls).toString();
+ u += 2; //super
+
+ final int ifc = readShort(bytecode, u);
+ u += 2;
+ u += ifc * 2;
+
+ final int fc = readShort(bytecode, u);
+ u += 2; //fields
+
+ for (int i = 0 ; i < fc ; i++) {
+ u += 2; //access
+ readShort(bytecode, u); //fieldname
+ u += 2; //name
+ u += 2; //descriptor
+ final int ac = readShort(bytecode, u);
+ u += 2;
+ //field attributes
+ for (int j = 0; j < ac; j++) {
+ u += 2; //attribute name
+ final int len = readInt(bytecode, u);
+ u += 4;
+ u += len;
+ }
+ }
+
+ final int mc = readShort(bytecode, u);
+ u += 2;
+ for (int i = 0 ; i < mc ; i++) {
+ readShort(bytecode, u);
+ u += 2; //access
+
+ final int methodNameIndex = readShort(bytecode, u);
+ u += 2;
+ final String methodName = cp.get(methodNameIndex).toString();
+
+ final int methodDescIndex = readShort(bytecode, u);
+ u += 2;
+ final String methodDesc = cp.get(methodDescIndex).toString();
+
+ final int ac = readShort(bytecode, u);
+ u += 2;
+
+ //method attributes
+ for (int j = 0; j < ac; j++) {
+ final int nameIndex = readShort(bytecode, u);
+ u += 2;
+ final String attrName = cp.get(nameIndex).toString();
+
+ final int attrLen = readInt(bytecode, u);
+ u += 4;
+
+ if ("Code".equals(attrName)) {
+ readShort(bytecode, u);
+ u += 2; //max stack
+ readShort(bytecode, u);
+ u += 2; //max locals
+ final int len = readInt(bytecode, u);
+ u += 4;
+ parseCode(bytecode, u, len, fullyQualifiedName(thisClassName, methodName, methodDesc));
+ u += len;
+ final int elen = readShort(bytecode, u); //exception table length
+ u += 2;
+ u += elen * 8;
+
+ //method attributes
+ final int ac2 = readShort(bytecode, u);
+ u += 2;
+ for (int k = 0; k < ac2; k++) {
+ u += 2; //name;
+ final int aclen = readInt(bytecode, u);
+ u += 4; //length
+ u += aclen; //bytes;
+ }
+ } else {
+ u += attrLen;
+ }
+ }
+ }
+
+ final int ac = readShort(bytecode, u);
+ u += 2;
+ //other attributes
+ for (int i = 0 ; i < ac ; i++) {
+ readShort(bytecode, u); //name index
+ u += 2;
+ final int len = readInt(bytecode, u);
+ u += 4;
+ u += len;
+ //attribute
+ }
+
+ return thisClassName;
+ }
+
+ private static String fullyQualifiedName(final String className, final String methodName, final String methodDesc) {
+ return className + '.' + methodName + methodDesc;
+ }
+
+ private void parseCode(final byte[] bytecode, final int index, final int len, final String desc) {
+ final List<Label> labels = new ArrayList<>();
+ labelMap.put(desc, labels);
+
+ boolean wide = false;
+
+ for (int i = index; i < index + len;) {
+ final int opcode = bytecode[i];
+ labels.add(new NashornLabel(opcode, i - index));
+
+ switch (opcode & 0xff) {
+ case 0xc4: //wide
+ wide = true;
+ i += 1;
+ break;
+ case 0xa9: //ret
+ i += wide ? 4 : 2;
+ break;
+ case 0xab: //lookupswitch
+ i += 1;
+ while (((i - index) & 3) != 0) {
+ i++;
+ }
+ readInt(bytecode, i);
+ i += 4; //defaultbyte
+ final int npairs = readInt(bytecode, i);
+ i += 4;
+ i += 8 * npairs;
+ break;
+ case 0xaa: //tableswitch
+ i += 1;
+ while (((i - index) & 3) != 0) {
+ i++;
+ }
+ readInt(bytecode, i); //default
+ i += 4;
+ final int lo = readInt(bytecode, i);
+ i += 4;
+ final int hi = readInt(bytecode, i);
+ i += 4;
+ i += 4 * (hi - lo + 1);
+ break;
+ case 0xc5: //multianewarray
+ i += 4;
+ break;
+ case 0x19: //aload (wide)
+ case 0x18: //dload
+ case 0x17: //fload
+ case 0x15: //iload
+ case 0x16: //lload
+ case 0x3a: //astore wide
+ case 0x39: //dstore
+ case 0x38: //fstore
+ case 0x36: //istore
+ case 0x37: //lstore
+ i += wide ? 3 : 2;
+ break;
+ case 0x10: //bipush
+ case 0x12: //ldc
+ case 0xbc: //anewarrayu
+ i += 2;
+ break;
+ case 0xb4: //getfield
+ case 0xb2: //getstatic
+ case 0xbd: //anewarray
+ case 0xc0: //checkcast
+ case 0xa5: //ifacmp_eq
+ case 0xa6: //ifacmp_ne
+ case 0x9f: //all ifs and ifcmps
+ case 0xa0:
+ case 0xa1:
+ case 0xa2:
+ case 0xa3:
+ case 0xa4:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0xc7:
+ case 0xc6:
+ case 0xc1: //instanceof
+ case 0xa7: //goto
+ case 0xb7: //special
+ case 0xb8: //static
+ case 0xb6: //virtual
+ case 0xa8: //jsr
+ case 0x13: //ldc_w
+ case 0x14: //ldc2_w
+ case 0xbb: //new
+ case 0xb5: //putfield
+ case 0xb3: //putstatic
+ case 0x11: //sipush
+ i += 3;
+ break;
+ case 0x84: //iinc (wide)
+ i += wide ? 5 : 3;
+ break;
+ case 0xba: //indy
+ case 0xb9: //interface
+ case 0xc8:
+ case 0xc9: //jsr_w
+ i += 5; //goto_w
+ break;
+ default:
+ i++;
+ break;
+ }
+
+ if (wide) {
+ wide = false;
+ }
+ }
+ }
+
+ @Override
+ public void accept(final ClassVisitor classVisitor, final Attribute[] attrs, final int flags) {
+ super.accept(classVisitor, attrs, flags);
+ }
+
+ @Override
+ protected Label readLabel(final int offset, final Label[] labels) {
+ final Label label = super.readLabel(offset, labels);
+ label.info = offset;
+ return label;
+ }
+
+ private abstract static class Constant {
+ protected ArrayList<Constant> cp;
+ protected int tag;
+ protected Constant(final ArrayList<Constant> cp, final int tag) {
+ this.cp = cp;
+ this.tag = tag;
+ }
+
+ @SuppressWarnings("unused")
+ final String getType() {
+ String str = type[tag];
+ while (str.length() < 16) {
+ str += " ";
+ }
+ return str;
+ }
+ }
+
+ private static class IndexInfo extends Constant {
+ protected final int index;
+
+ IndexInfo(final ArrayList<Constant> cp, final int tag, final int index) {
+ super(cp, tag);
+ this.index = index;
+ }
+
+ @Override
+ public String toString() {
+ return cp.get(index).toString();
+ }
+ }
+
+ private static class IndexInfo2 extends IndexInfo {
+ protected final int index2;
+
+ IndexInfo2(final ArrayList<Constant> cp, final int tag, final int index, final int index2) {
+ super(cp, tag, index);
+ this.index2 = index2;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + ' ' + cp.get(index2).toString();
+ }
+ }
+
+ private static class DirectInfo<T> extends Constant {
+ protected final T info;
+
+ DirectInfo(final ArrayList<Constant> cp, final int tag, final T info) {
+ super(cp, tag);
+ this.info = info;
+ }
+
+ @Override
+ public String toString() {
+ return info.toString();// + " [class=" + info.getClass().getSimpleName() + ']';
+ }
+ }
+
+ private static String type[] = {
+ //0
+ "<error>",
+ //1
+ "UTF8",
+ //2
+ "<error>",
+ //3
+ "Integer",
+ //4
+ "Float",
+ //5
+ "Long",
+ //6
+ "Double",
+ //7
+ "Class",
+ //8
+ "String",
+ //9
+ "Fieldref",
+ //10
+ "Methodref",
+ //11
+ "InterfaceMethodRef",
+ //12
+ "NameAndType",
+ //13
+ "<error>",
+ //14
+ "<error>",
+ //15
+ "MethodHandle",
+ //16
+ "MethodType",
+ //17
+ "<error>",
+ //18
+ "Invokedynamic"
+ };
+
+}
diff --git a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
new file mode 100644
index 00000000..5cdc67d4
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
@@ -0,0 +1,1257 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir.debug;
+
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.FLAGS_MASK;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.Handle;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.signature.SignatureReader;
+import jdk.internal.org.objectweb.asm.util.Printer;
+import jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+
+/**
+ * Pretty printer for --print-code.
+ * Also supports dot formats if --print-code has arguments
+ */
+public final class NashornTextifier extends Printer {
+
+ private String currentClassName;
+ private Iterator<Label> labelIter;
+ private Graph graph;
+ private String currentBlock;
+
+ // Following variables are used to govern the state of collapsing long sequences of NOP.
+ /** True if the last instruction was a NOP. */
+ private boolean lastWasNop = false;
+ /** True if ellipse ("...") was emitted in place of a second NOP. */
+ private boolean lastWasEllipse = false;
+
+ private static final int INTERNAL_NAME = 0;
+ private static final int FIELD_DESCRIPTOR = 1;
+ private static final int FIELD_SIGNATURE = 2;
+ private static final int METHOD_DESCRIPTOR = 3;
+ private static final int METHOD_SIGNATURE = 4;
+ private static final int CLASS_SIGNATURE = 5;
+
+ private final String tab = " ";
+ private final String tab2 = " ";
+ private final String tab3 = " ";
+
+ private Map<Label, String> labelNames;
+
+ private boolean localVarsStarted = false;
+
+ private NashornClassReader cr;
+ private ScriptEnvironment env;
+
+ /**
+ * Constructs a new {@link NashornTextifier}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #NashornTextifier(int)}
+ * version.
+ * @param env script environment
+ * @param cr a customized classreader for gathering, among other things, label
+ * information
+ */
+ public NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr) {
+ this(Opcodes.ASM5);
+ this.env = env;
+ this.cr = cr;
+ }
+
+ private NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr, final Iterator<Label> labelIter, final Graph graph) {
+ this(env, cr);
+ this.labelIter = labelIter;
+ this.graph = graph;
+ }
+
+ /**
+ * Constructs a new {@link NashornTextifier}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ protected NashornTextifier(final int api) {
+ super(api);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
+ final int major = version & 0xFFFF;
+ final int minor = version >>> 16;
+
+ currentClassName = name;
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append("// class version ").
+ append(major).
+ append('.').
+ append(minor).append(" (").
+ append(version).
+ append(")\n");
+
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append("// DEPRECATED\n");
+ }
+
+ sb.append("// access flags 0x"). //TODO TRANSLATE TO WHAT THEY MEAN
+ append(Integer.toHexString(access).toUpperCase()).
+ append('\n');
+
+ appendDescriptor(sb, CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ final TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+ final SignatureReader r = new SignatureReader(signature);
+ r.accept(sv);
+ sb.append("// declaration: ").
+ append(name).
+ append(sv.getDeclaration()).
+ append('\n');
+ }
+
+ appendAccess(sb, access & ~Opcodes.ACC_SUPER);
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ sb.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ sb.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) == 0) {
+ sb.append("class ");
+ }
+ appendDescriptor(sb, INTERNAL_NAME, name);
+
+ if (superName != null && !"java/lang/Object".equals(superName)) {
+ sb.append(" extends ");
+ appendDescriptor(sb, INTERNAL_NAME, superName);
+ sb.append(' ');
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ sb.append(" implements ");
+ for (final String interface1 : interfaces) {
+ appendDescriptor(sb, INTERNAL_NAME, interface1);
+ sb.append(' ');
+ }
+ }
+ sb.append(" {\n");
+
+ addText(sb);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ final StringBuilder sb = new StringBuilder();
+ if (file != null) {
+ sb.append(tab).
+ append("// compiled from: ").
+ append(file).
+ append('\n');
+ }
+ if (debug != null) {
+ sb.append(tab).
+ append("// debug info: ").
+ append(debug).
+ append('\n');
+ }
+ if (sb.length() > 0) {
+ addText(sb);
+ }
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name, final String desc) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(tab).append("outer class ");
+ appendDescriptor(sb, INTERNAL_NAME, owner);
+ sb.append(' ');
+ if (name != null) {
+ sb.append(name).append(' ');
+ }
+ appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public NashornTextifier visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+ final StringBuilder sb = new StringBuilder();
+// sb.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append(tab).append("// DEPRECATED\n");
+ }
+
+/* sb.append(tab).
+ append("// access flags 0x").
+ append(Integer.toHexString(access).toUpperCase()).
+ append('\n');
+*/
+
+ if (signature != null) {
+ sb.append(tab);
+ appendDescriptor(sb, FIELD_SIGNATURE, signature);
+
+ final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ final SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ sb.append(tab).
+ append("// declaration: ").
+ append(sv.getDeclaration()).
+ append('\n');
+ }
+
+ sb.append(tab);
+ appendAccess(sb, access);
+
+ final String prunedDesc = desc.endsWith(";") ? desc.substring(0, desc.length() - 1) : desc;
+ appendDescriptor(sb, FIELD_DESCRIPTOR, prunedDesc);
+ sb.append(' ').append(name);
+ if (value != null) {
+ sb.append(" = ");
+ if (value instanceof String) {
+ sb.append('\"').append(value).append('\"');
+ } else {
+ sb.append(value);
+ }
+ }
+
+ sb.append(";\n");
+ addText(sb);
+
+ final NashornTextifier t = createNashornTextifier();
+ addText(t.getText());
+
+ return t;
+ }
+
+ @Override
+ public NashornTextifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
+
+ graph = new Graph(name);
+
+ final List<Label> extraLabels = cr.getExtraLabels(currentClassName, name, desc);
+ this.labelIter = extraLabels == null ? null : extraLabels.iterator();
+
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append(tab).
+ append("// DEPRECATED\n");
+ }
+
+ sb.append(tab).
+ append("// access flags 0x").
+ append(Integer.toHexString(access).toUpperCase()).
+ append('\n');
+
+ if (signature != null) {
+ sb.append(tab);
+ appendDescriptor(sb, METHOD_SIGNATURE, signature);
+
+ final TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+ final SignatureReader r = new SignatureReader(signature);
+ r.accept(v);
+ final String genericDecl = v.getDeclaration();
+ final String genericReturn = v.getReturnType();
+ final String genericExceptions = v.getExceptions();
+
+ sb.append(tab).
+ append("// declaration: ").
+ append(genericReturn).
+ append(' ').
+ append(name).
+ append(genericDecl);
+
+ if (genericExceptions != null) {
+ sb.append(" throws ").append(genericExceptions);
+ }
+ sb.append('\n');
+ }
+
+ sb.append(tab);
+ appendAccess(sb, access);
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ sb.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ sb.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ sb.append("bridge ");
+ }
+
+ sb.append(name);
+ appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+ if (exceptions != null && exceptions.length > 0) {
+ sb.append(" throws ");
+ for (final String exception : exceptions) {
+ appendDescriptor(sb, INTERNAL_NAME, exception);
+ sb.append(' ');
+ }
+ }
+
+ sb.append('\n');
+ addText(sb);
+
+ final NashornTextifier t = createNashornTextifier();
+ addText(t.getText());
+ return t;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ addText("}\n");
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ //empty
+ }
+
+ @Override
+ public void visitParameter(final String name, final int access) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(tab2).append("// parameter ");
+ appendAccess(sb, access);
+ sb.append(' ').append(name == null ? "<no name>" : name)
+ .append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitCode() {
+ //empty
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("frame ");
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ sb.append("full [");
+ appendFrameTypes(sb, nLocal, local);
+ sb.append("] [");
+ appendFrameTypes(sb, nStack, stack);
+ sb.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ sb.append("append [");
+ appendFrameTypes(sb, nLocal, local);
+ sb.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ sb.append("chop ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ sb.append("same");
+ break;
+ case Opcodes.F_SAME1:
+ sb.append("same1 ");
+ appendFrameTypes(sb, 1, stack);
+ break;
+ default:
+ assert false;
+ break;
+ }
+ sb.append('\n');
+ sb.append('\n');
+ addText(sb);
+ }
+
+ private StringBuilder appendOpcode(final StringBuilder sb, final int opcode) {
+ final Label next = getNextLabel();
+ if (next instanceof NashornLabel) {
+ final int bci = next.getOffset();
+ if (bci != -1) {
+ final String bcis = "" + bci;
+ for (int i = 0; i < 5 - bcis.length(); i++) {
+ sb.append(' ');
+ }
+ sb.append(bcis);
+ sb.append(' ');
+ } else {
+ sb.append(" ");
+ }
+ }
+
+ return sb.append(tab2).append(OPCODES[opcode].toLowerCase());
+ }
+
+ private Label getNextLabel() {
+ return labelIter == null ? null : labelIter.next();
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if(opcode == Opcodes.NOP) {
+ if(lastWasEllipse) {
+ getNextLabel();
+ return;
+ } else if(lastWasNop) {
+ getNextLabel();
+ addText(" ...\n");
+ lastWasEllipse = true;
+ return;
+ } else {
+ lastWasNop = true;
+ }
+ } else {
+ lastWasNop = lastWasEllipse = false;
+ }
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append('\n');
+ addText(sb);
+ checkNoFallThru(opcode, null);
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode)
+ .append(' ')
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+ .toString(operand)).append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append(' ').append(var).append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append(' ');
+ appendDescriptor(sb, INTERNAL_NAME, type);
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append(' ');
+ appendDescriptor(sb, INTERNAL_NAME, owner);
+ sb.append('.').append(name).append(" : ");
+ appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append(' ');
+ appendDescriptor(sb, INTERNAL_NAME, owner);
+ sb.append('.').append(name);
+ appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(final String name, final String desc, final Handle bsm, final Object... bsmArgs) {
+ final StringBuilder sb = new StringBuilder();
+
+ appendOpcode(sb, Opcodes.INVOKEDYNAMIC).append(' ');
+ sb.append(name);
+ appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+ final int len = sb.length();
+ for (int i = 0; i < 80 - len ; i++) {
+ sb.append(' ');
+ }
+ sb.append(" [");
+ appendHandle(sb, bsm);
+ if (bsmArgs.length == 0) {
+ sb.append("none");
+ } else {
+ for (final Object cst : bsmArgs) {
+ if (cst instanceof String) {
+ appendStr(sb, (String)cst);
+ } else if (cst instanceof Type) {
+ sb.append(((Type)cst).getDescriptor()).append(".class");
+ } else if (cst instanceof Handle) {
+ appendHandle(sb, (Handle)cst);
+ } else if (cst instanceof Integer) {
+ final int c = (Integer)cst;
+ final int pp = c >> CALLSITE_PROGRAM_POINT_SHIFT;
+ if (pp != 0) {
+ sb.append(" pp=").append(pp);
+ }
+ sb.append(NashornCallSiteDescriptor.toString(c & FLAGS_MASK));
+ } else {
+ sb.append(cst);
+ }
+ sb.append(", ");
+ }
+ sb.setLength(sb.length() - 2);
+ }
+
+ sb.append("]\n");
+ addText(sb);
+ }
+
+ private static final boolean noFallThru(final int opcode) {
+ switch (opcode) {
+ case Opcodes.GOTO:
+ case Opcodes.ATHROW:
+ case Opcodes.ARETURN:
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void checkNoFallThru(final int opcode, final String to) {
+ if (noFallThru(opcode)) {
+ graph.setNoFallThru(currentBlock);
+ }
+
+ if (currentBlock != null && to != null) {
+ graph.addEdge(currentBlock, to);
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, opcode).append(' ');
+ final String to = appendLabel(sb, label);
+ sb.append('\n');
+ addText(sb);
+ checkNoFallThru(opcode, to);
+ }
+
+ private void addText(final Object t) {
+ text.add(t);
+ if (currentBlock != null) {
+ graph.addText(currentBlock, t.toString());
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ final String name = appendLabel(sb, label);
+ sb.append(" [bci=");
+ sb.append(label.info);
+ sb.append("]");
+ sb.append("\n");
+
+ graph.addNode(name);
+ if (currentBlock != null && !graph.isNoFallThru(currentBlock)) {
+ graph.addEdge(currentBlock, name);
+ }
+ currentBlock = name;
+ addText(sb);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, Opcodes.LDC).append(' ');
+ if (cst instanceof String) {
+ appendStr(sb, (String) cst);
+ } else if (cst instanceof Type) {
+ sb.append(((Type) cst).getDescriptor()).append(".class");
+ } else {
+ sb.append(cst);
+ }
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, Opcodes.IINC).append(' ');
+ sb.append(var).append(' ')
+ .append(increment).append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, Opcodes.TABLESWITCH).append(' ');
+ for (int i = 0; i < labels.length; ++i) {
+ sb.append(tab3).append(min + i).append(": ");
+ final String to = appendLabel(sb, labels[i]);
+ graph.addEdge(currentBlock, to);
+ sb.append('\n');
+ }
+ sb.append(tab3).append("default: ");
+ appendLabel(sb, dflt);
+ sb.append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, Opcodes.LOOKUPSWITCH).append(' ');
+ for (int i = 0; i < labels.length; ++i) {
+ sb.append(tab3).append(keys[i]).append(": ");
+ final String to = appendLabel(sb, labels[i]);
+ graph.addEdge(currentBlock, to);
+ sb.append('\n');
+ }
+ sb.append(tab3).append("default: ");
+ final String to = appendLabel(sb, dflt);
+ graph.addEdge(currentBlock, to);
+ sb.append('\n');
+ addText(sb.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ final StringBuilder sb = new StringBuilder();
+ appendOpcode(sb, Opcodes.MULTIANEWARRAY).append(' ');
+ appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+ sb.append(' ').append(dims).append('\n');
+ addText(sb);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(tab2).append("try ");
+ final String from = appendLabel(sb, start);
+ sb.append(' ');
+ appendLabel(sb, end);
+ sb.append(' ');
+ final String to = appendLabel(sb, handler);
+ sb.append(' ');
+ appendDescriptor(sb, INTERNAL_NAME, type);
+ sb.append('\n');
+ addText(sb);
+ graph.setIsCatch(to, type);
+ graph.addTryCatch(from, to);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,final String signature, final Label start, final Label end, final int index) {
+
+ final StringBuilder sb = new StringBuilder();
+ if (!localVarsStarted) {
+ text.add("\n");
+ localVarsStarted = true;
+ graph.addNode("vars");
+ currentBlock = "vars";
+ }
+
+ sb.append(tab2).append("local ").append(name).append(' ');
+ final int len = sb.length();
+ for (int i = 0; i < 25 - len; i++) {
+ sb.append(' ');
+ }
+ String label;
+
+ label = appendLabel(sb, start);
+ for (int i = 0; i < 5 - label.length(); i++) {
+ sb.append(' ');
+ }
+ label = appendLabel(sb, end);
+ for (int i = 0; i < 5 - label.length(); i++) {
+ sb.append(' ');
+ }
+
+ sb.append(index).append(tab2);
+
+ appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+ sb.append('\n');
+
+ if (signature != null) {
+ sb.append(tab2);
+ appendDescriptor(sb, FIELD_SIGNATURE, signature);
+
+ final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ final SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ sb.append(tab2).append("// declaration: ")
+ .append(sv.getDeclaration()).append('\n');
+ }
+ addText(sb.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("<line ");
+ sb.append(line);
+ sb.append(">\n");
+ addText(sb.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append('\n');
+ sb.append(tab2).append("max stack = ").append(maxStack);
+ sb.append(", max locals = ").append(maxLocals).append('\n');
+ addText(sb.toString());
+ }
+
+ private void printToDir(final Graph g) {
+ if (env._print_code_dir != null) {
+ final File dir = new File(env._print_code_dir);
+ if (!dir.exists() && !dir.mkdirs()) {
+ throw new RuntimeException(dir.toString());
+ }
+
+ File file;
+ int uniqueId = 0;
+ do {
+ final String fileName = g.getName() + (uniqueId == 0 ? "" : "_" + uniqueId) + ".dot";
+ file = new File(dir, fileName);
+ uniqueId++;
+ } while (file.exists());
+
+ try (PrintWriter pw = new PrintWriter(new FileOutputStream(file))) {
+ pw.println(g);
+ } catch (final FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ //here we need to do several bytecode guesses best upon the ldc instructions.
+ //for each instruction, assign bci. for an ldc/w/2w, guess a byte and keep
+ //iterating. if the next label is wrong, backtrack.
+ if (env._print_code_func == null || env._print_code_func.equals(graph.getName())) {
+ if (env._print_code_dir != null) {
+ printToDir(graph);
+ }
+ }
+ }
+
+ /**
+ * Creates a new TraceVisitor instance.
+ *
+ * @return a new TraceVisitor.
+ */
+ protected NashornTextifier createNashornTextifier() {
+ return new NashornTextifier(env, cr, labelIter, graph);
+ }
+
+ private static void appendDescriptor(final StringBuilder sb, final int type, final String desc) {
+ if (desc != null) {
+ if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE || type == METHOD_SIGNATURE) {
+ sb.append("// signature ").append(desc).append('\n');
+ } else {
+ appendShortDescriptor(sb, desc);
+ }
+ }
+ }
+
+ private String appendLabel(final StringBuilder sb, final Label l) {
+ if (labelNames == null) {
+ labelNames = new HashMap<>();
+ }
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(l, name);
+ }
+ sb.append(name);
+ return name;
+ }
+
+ private static void appendHandle(final StringBuilder sb, final Handle h) {
+ switch (h.getTag()) {
+ case Opcodes.H_GETFIELD:
+ sb.append("getfield");
+ break;
+ case Opcodes.H_GETSTATIC:
+ sb.append("getstatic");
+ break;
+ case Opcodes.H_PUTFIELD:
+ sb.append("putfield");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ sb.append("putstatic");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ sb.append("interface");
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ sb.append("special");
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ sb.append("static");
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ sb.append("virtual");
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ sb.append("new_special");
+ break;
+ default:
+ assert false;
+ break;
+ }
+ sb.append(" '");
+ sb.append(h.getName());
+ sb.append("'");
+ }
+
+ private static void appendAccess(final StringBuilder sb, final int access) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ sb.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ sb.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ sb.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ sb.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ sb.append("static ");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ sb.append("synchronized ");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ sb.append("volatile ");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ sb.append("transient ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ sb.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ sb.append("strictfp ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ sb.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_MANDATED) != 0) {
+ sb.append("mandated ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ sb.append("enum ");
+ }
+ }
+
+ private void appendFrameTypes(final StringBuilder sb, final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ sb.append(' ');
+ }
+ if (o[i] instanceof String) {
+ final String desc = (String) o[i];
+ if (desc.startsWith("[")) {
+ appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+ } else {
+ appendDescriptor(sb, INTERNAL_NAME, desc);
+ }
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer)o[i]).intValue()) {
+ case 0:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(sb, FIELD_DESCRIPTOR, "U");
+ break;
+ default:
+ assert false;
+ break;
+ }
+ } else {
+ appendLabel(sb, (Label) o[i]);
+ }
+ }
+ }
+
+ private static void appendShortDescriptor(final StringBuilder sb, final String desc) {
+ //final StringBuilder buf = new StringBuilder();
+ if (desc.charAt(0) == '(') {
+ for (int i = 0; i < desc.length(); i++) {
+ if (desc.charAt(i) == 'L') {
+ int slash = i;
+ while (desc.charAt(i) != ';') {
+ i++;
+ if (desc.charAt(i) == '/') {
+ slash = i;
+ }
+ }
+ sb.append(desc.substring(slash + 1, i)).append(';');
+ } else {
+ sb.append(desc.charAt(i));
+ }
+ }
+ } else {
+ final int lastSlash = desc.lastIndexOf('/');
+ final int lastBracket = desc.lastIndexOf('[');
+ if(lastBracket != -1) {
+ sb.append(desc, 0, lastBracket + 1);
+ }
+ sb.append(lastSlash == -1 ? desc : desc.substring(lastSlash + 1));
+ }
+ }
+
+ private static void appendStr(final StringBuilder sb, final String s) {
+ sb.append('\"');
+ for (int i = 0; i < s.length(); ++i) {
+ final char c = s.charAt(i);
+ if (c == '\n') {
+ sb.append("\\n");
+ } else if (c == '\r') {
+ sb.append("\\r");
+ } else if (c == '\\') {
+ sb.append("\\\\");
+ } else if (c == '"') {
+ sb.append("\\\"");
+ } else if (c < 0x20 || c > 0x7f) {
+ sb.append("\\u");
+ if (c < 0x10) {
+ sb.append("000");
+ } else if (c < 0x100) {
+ sb.append("00");
+ } else if (c < 0x1000) {
+ sb.append('0');
+ }
+ sb.append(Integer.toString(c, 16));
+ } else {
+ sb.append(c);
+ }
+ }
+ sb.append('\"');
+ }
+
+ private static class Graph {
+ private final LinkedHashSet<String> nodes;
+ private final Map<String, StringBuilder> contents;
+ private final Map<String, Set<String>> edges;
+ private final Set<String> hasPreds;
+ private final Set<String> noFallThru;
+ private final Map<String, String> catches;
+ private final Map<String, Set<String>> exceptionMap; //maps catch nodes to all their trys that can reach them
+ private final String name;
+
+ private static final String LEFT_ALIGN = "\\l";
+ private static final String COLOR_CATCH = "\"#ee9999\"";
+ private static final String COLOR_ORPHAN = "\"#9999bb\"";
+ private static final String COLOR_DEFAULT = "\"#99bb99\"";
+ private static final String COLOR_LOCALVARS = "\"#999999\"";
+
+ Graph(final String name) {
+ this.name = name;
+ this.nodes = new LinkedHashSet<>();
+ this.contents = new HashMap<>();
+ this.edges = new HashMap<>();
+ this.hasPreds = new HashSet<>();
+ this.catches = new HashMap<>();
+ this.noFallThru = new HashSet<>();
+ this.exceptionMap = new HashMap<>();
+ }
+
+ void addEdge(final String from, final String to) {
+ Set<String> edgeSet = edges.get(from);
+ if (edgeSet == null) {
+ edgeSet = new LinkedHashSet<>();
+ edges.put(from, edgeSet);
+ }
+ edgeSet.add(to);
+ hasPreds.add(to);
+ }
+
+ void addTryCatch(final String tryNode, final String catchNode) {
+ Set<String> tryNodes = exceptionMap.get(catchNode);
+ if (tryNodes == null) {
+ tryNodes = new HashSet<>();
+ exceptionMap.put(catchNode, tryNodes);
+ }
+ if (!tryNodes.contains(tryNode)) {
+ addEdge(tryNode, catchNode);
+ }
+ tryNodes.add(tryNode);
+ }
+
+ void addNode(final String node) {
+ assert !nodes.contains(node);
+ nodes.add(node);
+ }
+
+ void setNoFallThru(final String node) {
+ noFallThru.add(node);
+ }
+
+ boolean isNoFallThru(final String node) {
+ return noFallThru.contains(node);
+ }
+
+ void setIsCatch(final String node, final String exception) {
+ catches.put(node, exception);
+ }
+
+ String getName() {
+ return name;
+ }
+
+ void addText(final String node, final String text) {
+ StringBuilder sb = contents.get(node);
+ if (sb == null) {
+ sb = new StringBuilder();
+ }
+
+ for (int i = 0; i < text.length(); i++) {
+ switch (text.charAt(i)) {
+ case '\n':
+ sb.append(LEFT_ALIGN);
+ break;
+ case '"':
+ sb.append("'");
+ break;
+ default:
+ sb.append(text.charAt(i));
+ break;
+ }
+ }
+
+ contents.put(node, sb);
+ }
+
+ private static String dottyFriendly(final String name) {
+ return name.replace(':', '_');
+ }
+
+ @Override
+ public String toString() {
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append("digraph " + dottyFriendly(name) + " {");
+ sb.append("\n");
+ sb.append("\tgraph [fontname=courier]\n");
+ sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n");
+ sb.append("\tedge [fontname=courier]\n\n");
+
+ for (final String node : nodes) {
+ sb.append("\t");
+ sb.append(node);
+ sb.append(" [");
+ sb.append("id=");
+ sb.append(node);
+ sb.append(", label=\"");
+ String c = contents.get(node).toString();
+ if (c.startsWith(LEFT_ALIGN)) {
+ c = c.substring(LEFT_ALIGN.length());
+ }
+ final String ex = catches.get(node);
+ if (ex != null) {
+ sb.append("*** CATCH: ").append(ex).append(" ***\n");
+ }
+ sb.append(c);
+ sb.append("\"]\n");
+ }
+
+ for (final String from : edges.keySet()) {
+ for (final String to : edges.get(from)) {
+ sb.append("\t");
+ sb.append(from);
+ sb.append(" -> ");
+ sb.append(to);
+ sb.append("[label=\"");
+ sb.append(to);
+ sb.append("\"");
+ if (catches.get(to) != null) {
+ sb.append(", color=red, style=dashed");
+ }
+ sb.append(']');
+ sb.append(";\n");
+ }
+ }
+
+ sb.append("\n");
+ for (final String node : nodes) {
+ sb.append("\t");
+ sb.append(node);
+ sb.append(" [shape=box");
+ if (catches.get(node) != null) {
+ sb.append(", color=" + COLOR_CATCH);
+ } else if ("vars".equals(node)) {
+ sb.append(", shape=hexagon, color=" + COLOR_LOCALVARS);
+ } else if (!hasPreds.contains(node)) {
+ sb.append(", color=" + COLOR_ORPHAN);
+ }
+ sb.append("]\n");
+ }
+
+ sb.append("}\n");
+ return sb.toString();
+ }
+ }
+
+ static class NashornLabel extends Label {
+ final Label label;
+ final int bci;
+ final int opcode;
+
+ NashornLabel(final Label label, final int bci) {
+ this.label = label;
+ this.bci = bci;
+ this.opcode = -1;
+ }
+
+ //not an ASM label
+ NashornLabel(final int opcode, final int bci) {
+ this.opcode = opcode;
+ this.bci = bci;
+ this.label = null;
+ }
+
+ Label getLabel() {
+ return label;
+ }
+
+ @Override
+ public int getOffset() {
+ return bci;
+ }
+
+ @Override
+ public String toString() {
+ return "label " + bci;
+ }
+ }
+
+ @Override
+ public Printer visitAnnotationDefault() {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Printer visitClassAnnotation(final String arg0, final boolean arg1) {
+ return this;
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute arg0) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Printer visitFieldAnnotation(final String arg0, final boolean arg1) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute arg0) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Printer visitMethodAnnotation(final String arg0, final boolean arg1) {
+ return this;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute arg0) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Printer visitParameterAnnotation(final int arg0, final String arg1, final boolean arg2) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public void visit(final String arg0, final Object arg1) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Printer visitAnnotation(final String arg0, final String arg1) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ //empty
+ }
+
+ @Override
+ public Printer visitArray(final String arg0) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public void visitEnum(final String arg0, final String arg1, final String arg2) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public void visitInnerClass(final String arg0, final String arg1, final String arg2, final int arg3) {
+ throw new AssertionError();
+ }
+}
diff --git a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
index 89269d5f..53a09a68 100644
--- a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
+++ b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
@@ -52,9 +52,7 @@ import java.util.Map;
* this fact and will report incorrect sizes, as it will presume the default JVM
* behavior.
*/
-
-@SuppressWarnings("StaticNonFinalUsedInInitialization")
-public class ObjectSizeCalculator {
+public final class ObjectSizeCalculator {
/**
* Describes constant memory overheads for various constructs in a JVM implementation.
@@ -307,7 +305,7 @@ public class ObjectSizeCalculator {
public ClassSizeInfo(final Class<?> clazz) {
long newFieldsSize = 0;
final List<Field> newReferenceFields = new LinkedList<>();
- for (Field f : clazz.getDeclaredFields()) {
+ for (final Field f : clazz.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
continue;
}
@@ -338,10 +336,10 @@ public class ObjectSizeCalculator {
}
public void enqueueReferencedObjects(final Object obj, final ObjectSizeCalculator calc) {
- for (Field f : referenceFields) {
+ for (final Field f : referenceFields) {
try {
calc.enqueue(f.get(obj));
- } catch (IllegalAccessException e) {
+ } catch (final IllegalAccessException e) {
final AssertionError ae = new AssertionError(
"Unexpected denial of access to " + f);
ae.initCause(e);
diff --git a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
index 09af647d..52e9b663 100644
--- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
+++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
@@ -29,18 +29,25 @@ import java.util.List;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.BlockStatement;
+import jdk.nashorn.internal.ir.BreakNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.ThrowNode;
import jdk.nashorn.internal.ir.TryNode;
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
@@ -70,25 +77,30 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
/** Print line numbers */
private final boolean printLineNumbers;
+ /** Print inferred and optimistic types */
+ private final boolean printTypes;
+
private int lastLineNumber = -1;
/**
* Constructor.
*/
public PrintVisitor() {
- this(true);
+ this(true, true);
}
/**
* Constructor
*
* @param printLineNumbers should line number nodes be included in the output?
+ * @param printTypes should we print optimistic and inferred types?
*/
- public PrintVisitor(final boolean printLineNumbers) {
+ public PrintVisitor(final boolean printLineNumbers, final boolean printTypes) {
super(new LexicalContext());
this.EOLN = System.lineSeparator();
this.sb = new StringBuilder();
this.printLineNumbers = printLineNumbers;
+ this.printTypes = printTypes;
}
/**
@@ -97,7 +109,7 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
* @param root a node from which to start printing code
*/
public PrintVisitor(final Node root) {
- this(root, true);
+ this(root, true, true);
}
/**
@@ -105,9 +117,10 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
*
* @param root a node from which to start printing code
* @param printLineNumbers should line numbers nodes be included in the output?
+ * @param printTypes should we print optimistic and inferred types?
*/
- public PrintVisitor(final Node root, final boolean printLineNumbers) {
- this(printLineNumbers);
+ public PrintVisitor(final Node root, final boolean printLineNumbers, final boolean printTypes) {
+ this(printLineNumbers, printTypes);
visit(root);
}
@@ -135,7 +148,28 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterDefault(final Node node) {
- node.toString(sb);
+ node.toString(sb, printTypes);
+ return false;
+ }
+
+ @Override
+ public boolean enterContinueNode(final ContinueNode node) {
+ node.toString(sb, printTypes);
+ printLocalVariableConversion(node);
+ return false;
+ }
+
+ @Override
+ public boolean enterBreakNode(final BreakNode node) {
+ node.toString(sb, printTypes);
+ printLocalVariableConversion(node);
+ return false;
+ }
+
+ @Override
+ public boolean enterThrowNode(final ThrowNode node) {
+ node.toString(sb, printTypes);
+ printLocalVariableConversion(node);
return false;
}
@@ -148,9 +182,9 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
final List<Statement> statements = block.getStatements();
- for (final Node statement : statements) {
- if (printLineNumbers && (statement instanceof Statement)) {
- final int lineNumber = ((Statement)statement).getLineNumber();
+ for (final Statement statement : statements) {
+ if (printLineNumbers) {
+ final int lineNumber = statement.getLineNumber();
sb.append('\n');
if (lineNumber != lastLineNumber) {
indent();
@@ -162,10 +196,6 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
statement.accept(this);
- if (statement instanceof FunctionNode) {
- continue;
- }
-
int lastIndex = sb.length() - 1;
char lastChar = sb.charAt(lastIndex);
while (Character.isWhitespace(lastChar) && lastIndex >= 0) {
@@ -190,6 +220,7 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
sb.append(EOLN);
indent();
sb.append('}');
+ printLocalVariableConversion(block);
return false;
}
@@ -211,13 +242,31 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
}
@Override
+ public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+ expr.getExpression().accept(this);
+ printLocalVariableConversion(expr);
+ return false;
+ }
+
+ @Override
+ public boolean enterIdentNode(final IdentNode identNode) {
+ identNode.toString(sb, printTypes);
+ printLocalVariableConversion(identNode);
+ return true;
+ }
+
+ private void printLocalVariableConversion(final JoinPredecessor joinPredecessor) {
+ LocalVariableConversion.toString(joinPredecessor.getLocalVariableConversion(), sb);
+ }
+
+ @Override
public boolean enterUnaryNode(final UnaryNode unaryNode) {
unaryNode.toString(sb, new Runnable() {
@Override
public void run() {
- unaryNode.rhs().accept(PrintVisitor.this);
+ unaryNode.getExpression().accept(PrintVisitor.this);
}
- });
+ }, printTypes);
return false;
}
@@ -229,21 +278,21 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterForNode(final ForNode forNode) {
- forNode.toString(sb);
+ forNode.toString(sb, printTypes);
forNode.getBody().accept(this);
return false;
}
@Override
public boolean enterFunctionNode(final FunctionNode functionNode) {
- functionNode.toString(sb);
+ functionNode.toString(sb, printTypes);
enterBlock(functionNode.getBody());
return false;
}
@Override
public boolean enterIfNode(final IfNode ifNode) {
- ifNode.toString(sb);
+ ifNode.toString(sb, printTypes);
ifNode.getPass().accept(this);
final Block fail = ifNode.getFail();
@@ -252,7 +301,12 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
sb.append(" else ");
fail.accept(this);
}
-
+ if(ifNode.getLocalVariableConversion() != null) {
+ assert fail == null;
+ sb.append(" else ");
+ printLocalVariableConversion(ifNode);
+ sb.append(";");
+ }
return false;
}
@@ -261,15 +315,15 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
indent -= TABWIDTH;
indent();
indent += TABWIDTH;
- labeledNode.toString(sb);
+ labeledNode.toString(sb, printTypes);
labeledNode.getBody().accept(this);
-
+ printLocalVariableConversion(labeledNode);
return false;
}
@Override
public boolean enterSplitNode(final SplitNode splitNode) {
- splitNode.toString(sb);
+ splitNode.toString(sb, printTypes);
sb.append(EOLN);
indent += TABWIDTH;
indent();
@@ -287,7 +341,7 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterSwitchNode(final SwitchNode switchNode) {
- switchNode.toString(sb);
+ switchNode.toString(sb, printTypes);
sb.append(" {");
final List<CaseNode> cases = switchNode.getCases();
@@ -295,13 +349,20 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
for (final CaseNode caseNode : cases) {
sb.append(EOLN);
indent();
- caseNode.toString(sb);
+ caseNode.toString(sb, printTypes);
+ printLocalVariableConversion(caseNode);
indent += TABWIDTH;
caseNode.getBody().accept(this);
indent -= TABWIDTH;
sb.append(EOLN);
}
-
+ if(switchNode.getLocalVariableConversion() != null) {
+ sb.append(EOLN);
+ indent();
+ sb.append("default: ");
+ printLocalVariableConversion(switchNode);
+ sb.append("{}");
+ }
sb.append(EOLN);
indent();
sb.append("}");
@@ -311,14 +372,15 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterTryNode(final TryNode tryNode) {
- tryNode.toString(sb);
+ tryNode.toString(sb, printTypes);
+ printLocalVariableConversion(tryNode);
tryNode.getBody().accept(this);
final List<Block> catchBlocks = tryNode.getCatchBlocks();
for (final Block catchBlock : catchBlocks) {
final CatchNode catchNode = (CatchNode)catchBlock.getStatements().get(0);
- catchNode.toString(sb);
+ catchNode.toString(sb, printTypes);
catchNode.getBody().accept(this);
}
@@ -335,7 +397,8 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterVarNode(final VarNode varNode) {
sb.append("var ");
- varNode.getName().toString(sb);
+ varNode.getName().toString(sb, printTypes);
+ printLocalVariableConversion(varNode.getName());
final Node init = varNode.getInit();
if (init != null) {
sb.append(" = ");
@@ -347,13 +410,14 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterWhileNode(final WhileNode whileNode) {
+ printLocalVariableConversion(whileNode);
if (whileNode.isDoWhile()) {
sb.append("do");
whileNode.getBody().accept(this);
sb.append(' ');
- whileNode.toString(sb);
+ whileNode.toString(sb, printTypes);
} else {
- whileNode.toString(sb);
+ whileNode.toString(sb, printTypes);
whileNode.getBody().accept(this);
}
@@ -362,7 +426,7 @@ public final class PrintVisitor extends NodeVisitor<LexicalContext> {
@Override
public boolean enterWithNode(final WithNode withNode) {
- withNode.toString(sb);
+ withNode.toString(sb, printTypes);
withNode.getBody().accept(this);
return false;
diff --git a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
index 2b1de7c7..1582f30e 100644
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
@@ -53,8 +53,6 @@ public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T
return enterBIT_NOT(unaryNode);
case DELETE:
return enterDELETE(unaryNode);
- case DISCARD:
- return enterDISCARD(unaryNode);
case NEW:
return enterNEW(unaryNode);
case NOT:
@@ -84,8 +82,6 @@ public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T
return leaveBIT_NOT(unaryNode);
case DELETE:
return leaveDELETE(unaryNode);
- case DISCARD:
- return leaveDISCARD(unaryNode);
case NEW:
return leaveNEW(unaryNode);
case NOT:
@@ -359,26 +355,6 @@ public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T
}
/**
- * Unary enter - callback for entering a discard operator
- *
- * @param unaryNode the node
- * @return true if traversal should continue and node children be traversed, false otherwise
- */
- public boolean enterDISCARD(final UnaryNode unaryNode) {
- return enterDefault(unaryNode);
- }
-
- /**
- * Unary leave - callback for leaving a discard operator
- *
- * @param unaryNode the node
- * @return processed node, which will replace the original one, or the original node
- */
- public Node leaveDISCARD(final UnaryNode unaryNode) {
- return leaveDefault(unaryNode);
- }
-
- /**
* Unary enter - callback for entering a new operator
*
* @param unaryNode the node
diff --git a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
index 4dc55b33..f9fd3862 100644
--- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
@@ -38,9 +38,11 @@ import jdk.nashorn.internal.ir.EmptyNode;
import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.GetSplitState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
@@ -49,7 +51,9 @@ import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.ReturnNode;
import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.SetSplitState;
import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.SplitReturn;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.TernaryNode;
import jdk.nashorn.internal.ir.ThrowNode;
@@ -389,6 +393,26 @@ public abstract class NodeVisitor<T extends LexicalContext> {
}
/**
+ * Callback for entering a {@link GetSplitState}.
+ *
+ * @param getSplitState the get split state expression
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterGetSplitState(final GetSplitState getSplitState) {
+ return enterDefault(getSplitState);
+ }
+
+ /**
+ * Callback for leaving a {@link GetSplitState}.
+ *
+ * @param getSplitState the get split state expression
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveGetSplitState(final GetSplitState getSplitState) {
+ return leaveDefault(getSplitState);
+ }
+
+ /**
* Callback for entering an IdentNode
*
* @param identNode the node
@@ -569,6 +593,26 @@ public abstract class NodeVisitor<T extends LexicalContext> {
}
/**
+ * Callback for entering a {@link SetSplitState}.
+ *
+ * @param setSplitState the set split state statement
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterSetSplitState(final SetSplitState setSplitState) {
+ return enterDefault(setSplitState);
+ }
+
+ /**
+ * Callback for leaving a {@link SetSplitState}.
+ *
+ * @param setSplitState the set split state expression
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveSetSplitState(final SetSplitState setSplitState) {
+ return leaveDefault(setSplitState);
+ }
+
+ /**
* Callback for entering a SplitNode
*
* @param splitNode the node
@@ -589,6 +633,26 @@ public abstract class NodeVisitor<T extends LexicalContext> {
}
/**
+ * Callback for entering a SplitReturn
+ *
+ * @param splitReturn the node
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterSplitReturn(final SplitReturn splitReturn) {
+ return enterDefault(splitReturn);
+ }
+
+ /**
+ * Callback for leaving a SplitReturn
+ *
+ * @param splitReturn the node
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveSplitReturn(final SplitReturn splitReturn) {
+ return leaveDefault(splitReturn);
+ }
+
+ /**
* Callback for entering a SwitchNode
*
* @param switchNode the node
@@ -689,6 +753,27 @@ public abstract class NodeVisitor<T extends LexicalContext> {
}
/**
+ * Callback for entering a {@link JoinPredecessorExpression}.
+ *
+ * @param expr the join predecessor expression
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+ return enterDefault(expr);
+ }
+
+ /**
+ * Callback for leaving a {@link JoinPredecessorExpression}.
+ *
+ * @param expr the join predecessor expression
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+ return leaveDefault(expr);
+ }
+
+
+ /**
* Callback for entering a VarNode
*
* @param varNode the node
diff --git a/src/jdk/nashorn/internal/lookup/Lookup.java b/src/jdk/nashorn/internal/lookup/Lookup.java
index 0dd2741e..57728509 100644
--- a/src/jdk/nashorn/internal/lookup/Lookup.java
+++ b/src/jdk/nashorn/internal/lookup/Lookup.java
@@ -68,6 +68,12 @@ public final class Lookup {
/** Method handle to the most generic of setters, the one that takes an Object */
public static final MethodType SET_OBJECT_TYPE = MH.type(void.class, Object.class, Object.class);
+ /** Method handle to the primitive getters, the one that returns an long/int/double */
+ public static final MethodType GET_PRIMITIVE_TYPE = MH.type(long.class, Object.class);
+
+ /** Method handle to the primitive getters, the one that returns an long/int/double */
+ public static final MethodType SET_PRIMITIVE_TYPE = MH.type(void.class, Object.class, long.class);
+
private Lookup() {
}
@@ -123,6 +129,53 @@ public final class Lookup {
}
/**
+ * This method filters primitive argument types using JavaScript semantics. For example,
+ * an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it.
+ * If you are returning values to JavaScript that have to be of a specific type, this is
+ * the correct return value filter to use, as the explicitCastArguments just uses the
+ * Java boxing equivalents
+ *
+ * @param mh method handle for which to filter argument value
+ * @param n argument index
+ * @param from old argument type, the new one is given by the sent method handle
+ * @return method handle for appropriate argument type conversion
+ */
+ public static MethodHandle filterArgumentType(final MethodHandle mh, final int n, final Class<?> from) {
+ final Class<?> to = mh.type().parameterType(n);
+
+ if (from == int.class) {
+ //fallthru
+ } else if (from == long.class) {
+ if (to == int.class) {
+ return MH.filterArguments(mh, n, JSType.TO_INT32_L.methodHandle());
+ }
+ //fallthru
+ } else if (from == double.class) {
+ if (to == int.class) {
+ return MH.filterArguments(mh, n, JSType.TO_INT32_D.methodHandle());
+ } else if (to == long.class) {
+ return MH.filterArguments(mh, n, JSType.TO_UINT32_D.methodHandle());
+ }
+ //fallthru
+ } else if (!from.isPrimitive()) {
+ if (to == int.class) {
+ return MH.filterArguments(mh, n, JSType.TO_INT32.methodHandle());
+ } else if (to == long.class) {
+ return MH.filterArguments(mh, n, JSType.TO_UINT32.methodHandle());
+ } else if (to == double.class) {
+ return MH.filterArguments(mh, n, JSType.TO_NUMBER.methodHandle());
+ } else if (!to.isPrimitive()) {
+ return mh;
+ }
+
+ assert false : "unsupported Lookup.filterReturnType type " + from + " -> " + to;
+ }
+
+ //use a standard cast - we don't need to check JavaScript special cases
+ return MH.explicitCastArguments(mh, mh.type().changeParameterType(n, from));
+ }
+
+ /**
* This method filters primitive return types using JavaScript semantics. For example,
* an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it.
* If you are returning values to JavaScript that have to be of a specific type, this is
@@ -139,6 +192,9 @@ public final class Lookup {
if (retType == int.class) {
//fallthru
} else if (retType == long.class) {
+ if (type == int.class) {
+ return MH.filterReturnValue(mh, JSType.TO_INT32_L.methodHandle());
+ }
//fallthru
} else if (retType == double.class) {
if (type == int.class) {
diff --git a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
index 34fe2eb6..8e5120f2 100644
--- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
+++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
@@ -37,15 +37,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
import jdk.nashorn.internal.runtime.options.Options;
/**
* This class is abstraction for all method handle, switchpoint and method type
* operations. This enables the functionality interface to be subclassed and
- * intrumensted, as it has been proven vital to keep the number of method
+ * instrumented, as it has been proven vital to keep the number of method
* handles in the system down.
*
* All operations of the above type should go through this class, and not
@@ -96,27 +99,9 @@ public final class MethodHandleFactory {
return obj.toString();
}
- private static final MethodHandleFunctionality STANDARD = new StandardMethodHandleFunctionality();
- private static final MethodHandleFunctionality FUNC;
-
- private static final String DEBUG_PROPERTY = "nashorn.methodhandles.debug";
- private static final DebugLogger LOG = new DebugLogger("methodhandles", DEBUG_PROPERTY);
-
- static {
- if (LOG.isEnabled() || Options.getBooleanProperty(DEBUG_PROPERTY)) {
- if (Options.getStringProperty(DEBUG_PROPERTY, "").equals("create")) {
- FUNC = new TraceCreateMethodHandleFunctionality();
- } else {
- FUNC = new TraceMethodHandleFunctionality();
- }
- } else {
- FUNC = STANDARD;
- }
- }
-
+ private static final MethodHandleFunctionality FUNC = new StandardMethodHandleFunctionality();
private static final boolean PRINT_STACKTRACE = Options.getBooleanProperty("nashorn.methodhandles.debug.stacktrace");
-
/**
* Return the method handle functionality used for all method handle operations
* @return a method handle functionality implementation
@@ -125,8 +110,15 @@ public final class MethodHandleFactory {
return FUNC;
}
- private static final MethodHandle TRACE = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
- private static final MethodHandle TRACE_RETURN = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
+ private static final MethodHandle TRACE = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
+ private static final MethodHandle TRACE_RETURN = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
+ private static final MethodHandle TRACE_RETURN_VOID = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturnVoid", MethodType.methodType(void.class, DebugLogger.class));
+
+ private static final String VOID_TAG = "[VOID]";
+
+ private static void err(final String str) {
+ Context.getContext().getErr().println(str);
+ }
/**
* Tracer that is applied before a value is returned from the traced function. It will output the return
@@ -136,11 +128,23 @@ public final class MethodHandleFactory {
* @return return value unmodified
*/
static Object traceReturn(final DebugLogger logger, final Object value) {
- final String str = "\treturn: " + stripName(value) + " [type=" + (value == null ? "null" : stripName(value.getClass()) + ']');
- logger.log(TRACE_LEVEL, str);
+ final String str = " return" +
+ (VOID_TAG.equals(value) ?
+ ";" :
+ " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
+ if (logger == null) {
+ err(str);
+ } else if (logger.isEnabled()) {
+ logger.log(TRACE_LEVEL, str);
+ }
+
return value;
}
+ static void traceReturnVoid(final DebugLogger logger) {
+ traceReturn(logger, VOID_TAG);
+ }
+
/**
* Tracer that is applied before a function is called, printing the arguments
*
@@ -172,8 +176,11 @@ public final class MethodHandleFactory {
}
}
- assert logger != null;
- logger.log(TRACE_LEVEL, sb);
+ if (logger == null) {
+ err(sb.toString());
+ } else {
+ logger.log(TRACE_LEVEL, sb);
+ }
stacktrace(logger);
}
@@ -184,7 +191,12 @@ public final class MethodHandleFactory {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
new Throwable().printStackTrace(ps);
- logger.log(TRACE_LEVEL, baos.toString());
+ final String st = baos.toString();
+ if (logger == null) {
+ err(st);
+ } else {
+ logger.log(TRACE_LEVEL, st);
+ }
}
private static String argString(final Object arg) {
@@ -203,8 +215,8 @@ public final class MethodHandleFactory {
if (arg instanceof ScriptObject) {
return arg.toString() +
- " (map=" + Debug.id((((ScriptObject)arg).getMap())) +
- ")";
+ " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
+ ')';
}
return arg.toString();
@@ -212,35 +224,63 @@ public final class MethodHandleFactory {
/**
* Add a debug printout to a method handle, tracing parameters and return values
+ * Output will be unconditional to stderr
*
- * @param logger a specific logger to which to write the output
* @param mh method handle to trace
* @param tag start of trace message
* @return traced method handle
*/
- public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final Object tag) {
- return addDebugPrintout(logger, mh, 0, true, tag);
+ public static MethodHandle addDebugPrintout(final MethodHandle mh, final Object tag) {
+ return addDebugPrintout(null, Level.OFF, mh, 0, true, tag);
}
+ /**
+ * Add a debug printout to a method handle, tracing parameters and return values
+ *
+ * @param logger a specific logger to which to write the output
+ * @param level level over which to print
+ * @param mh method handle to trace
+ * @param tag start of trace message
+ * @return traced method handle
+ */
+ public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final Object tag) {
+ return addDebugPrintout(logger, level, mh, 0, true, tag);
+ }
/**
* Add a debug printout to a method handle, tracing parameters and return values
+ * Output will be unconditional to stderr
+ *
+ * @param mh method handle to trace
+ * @param paramStart first param to print/trace
+ * @param printReturnValue should we print/trace return value if available?
+ * @param tag start of trace message
+ * @return traced method handle
+ */
+ public static MethodHandle addDebugPrintout(final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
+ return addDebugPrintout(null, Level.OFF, mh, paramStart, printReturnValue, tag);
+ }
+
+ /**
+ * Add a debug printout to a method handle, tracing parameters and return values
*
* @param logger a specific logger to which to write the output
+ * @param level level over which to print
* @param mh method handle to trace
* @param paramStart first param to print/trace
* @param printReturnValue should we print/trace return value if available?
* @param tag start of trace message
* @return traced method handle
*/
- public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
+ public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
final MethodType type = mh.type();
- if (logger != null && logger.levelAbove(TRACE_LEVEL)) {
+ //if there is no logger, or if it's set to log only coarser events
+ //than the trace level, skip and return
+ if (logger != null && logger.levelCoarserThan(level)) {
return mh;
}
- assert logger != null;
assert TRACE != null;
MethodHandle trace = MethodHandles.insertArguments(TRACE, 0, logger, tag, paramStart);
@@ -253,191 +293,49 @@ public final class MethodHandleFactory {
asType(type.changeReturnType(void.class)));
final Class<?> retType = type.returnType();
- if (retType != void.class && printReturnValue) {
- final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
- trace = MethodHandles.filterReturnValue(trace,
- traceReturn.asType(
- traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+ if (printReturnValue) {
+ if (retType != void.class) {
+ final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
+ trace = MethodHandles.filterReturnValue(trace,
+ traceReturn.asType(
+ traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+ } else {
+ trace = MethodHandles.filterReturnValue(trace, MethodHandles.insertArguments(TRACE_RETURN_VOID, 0, logger));
+ }
}
return trace;
}
/**
- * The standard class that marshalls all method handle operations to the java.lang.invoke
+ * Class that marshalls all method handle operations to the java.lang.invoke
* package. This exists only so that it can be subclassed and method handles created from
* Nashorn made possible to instrument.
*
* All Nashorn classes should use the MethodHandleFactory for their method handle operations
*/
- private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality {
+ @Logger(name="methodhandles")
+ private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality, Loggable {
- @Override
- public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
- return MethodHandles.filterArguments(target, pos, filters);
- }
-
- @Override
- public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
- return MethodHandles.filterReturnValue(target, filter);
- }
+ // for bootstrapping reasons, because a lot of static fields use MH for lookups, we
+ // need to set the logger when the Global object is finished. This means that we don't
+ // get instrumentation for public static final MethodHandle SOMETHING = MH... in the builtin
+ // classes, but that doesn't matter, because this is usually not where we want it
+ private DebugLogger log = DebugLogger.DISABLED_LOGGER;
- @Override
- public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
- return MethodHandles.guardWithTest(test, target, fallback);
+ public StandardMethodHandleFunctionality() {
}
@Override
- public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
- return MethodHandles.insertArguments(target, pos, values);
+ public DebugLogger initLogger(final Context context) {
+ return this.log = context.getLogger(this.getClass());
}
@Override
- public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... valueTypes) {
- return MethodHandles.dropArguments(target, pos, valueTypes);
- }
-
- @Override
- public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes) {
- return MethodHandles.dropArguments(target, pos, valueTypes);
- }
-
- @Override
- public MethodHandle asType(final MethodHandle handle, final MethodType type) {
- return handle.asType(type);
- }
-
- @Override
- public MethodHandle bindTo(final MethodHandle handle, final Object x) {
- return handle.bindTo(x);
- }
-
- @Override
- public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
- return MethodHandles.foldArguments(target, combiner);
- }
-
- @Override
- public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
- return MethodHandles.explicitCastArguments(target, type);
- }
-
- @Override
- public MethodHandle arrayElementGetter(final Class<?> type) {
- return MethodHandles.arrayElementGetter(type);
- }
-
- @Override
- public MethodHandle arrayElementSetter(final Class<?> type) {
- return MethodHandles.arrayElementSetter(type);
- }
-
- @Override
- public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
- return MethodHandles.throwException(returnType, exType);
- }
-
- @Override
- public MethodHandle constant(final Class<?> type, final Object value) {
- return MethodHandles.constant(type, value);
- }
-
- @Override
- public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
- return handle.asCollector(arrayType, arrayLength);
- }
-
- @Override
- public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
- return handle.asSpreader(arrayType, arrayLength);
- }
-
- @Override
- public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- try {
- return explicitLookup.findGetter(clazz, name, type);
- } catch (final NoSuchFieldException | IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- try {
- return explicitLookup.findStaticGetter(clazz, name, type);
- } catch (final NoSuchFieldException | IllegalAccessException e) {
- throw new LookupException(e);
- }
+ public DebugLogger getLogger() {
+ return log;
}
-
- @Override
- public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- try {
- return explicitLookup.findSetter(clazz, name, type);
- } catch (final NoSuchFieldException | IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- try {
- return explicitLookup.findStaticSetter(clazz, name, type);
- } catch (final NoSuchFieldException | IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public MethodHandle find(final Method method) {
- try {
- return PUBLIC_LOOKUP.unreflect(method);
- } catch (final IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
- try {
- return explicitLookup.findStatic(clazz, name, type);
- } catch (final NoSuchMethodException | IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
- try {
- return explicitLookup.findVirtual(clazz, name, type);
- } catch (final NoSuchMethodException | IllegalAccessException e) {
- throw new LookupException(e);
- }
- }
-
- @Override
- public SwitchPoint createSwitchPoint() {
- return new SwitchPoint();
- }
-
- @Override
- public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
- return sp.guardWithTest(before, after);
- }
-
- @Override
- public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
- return MethodType.methodType(returnType, paramTypes);
- }
-
- }
-
- /**
- * Class used for instrumenting and debugging Nashorn generated method handles
- */
- private static class TraceMethodHandleFunctionality extends StandardMethodHandleFunctionality {
-
protected static String describe(final Object... data) {
final StringBuilder sb = new StringBuilder();
@@ -470,177 +368,221 @@ public final class MethodHandleFactory {
}
public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
- return addDebugPrintout(LOG, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
+ if (log.isEnabled()) {
+ if (PRINT_STACKTRACE) {
+ stacktrace(log);
+ }
+ return addDebugPrintout(log, Level.INFO, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
+ }
+ return master;
}
@Override
public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
- final MethodHandle mh = super.filterArguments(target, pos, filters);
+ final MethodHandle mh = MethodHandles.filterArguments(target, pos, filters);
return debug(mh, "filterArguments", target, pos, filters);
}
@Override
public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
- final MethodHandle mh = super.filterReturnValue(target, filter);
+ final MethodHandle mh = MethodHandles.filterReturnValue(target, filter);
return debug(mh, "filterReturnValue", target, filter);
}
@Override
public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
- final MethodHandle mh = super.guardWithTest(test, target, fallback);
+ final MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
return debug(mh, "guardWithTest", test, target, fallback);
}
@Override
public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
- final MethodHandle mh = super.insertArguments(target, pos, values);
+ final MethodHandle mh = MethodHandles.insertArguments(target, pos, values);
return debug(mh, "insertArguments", target, pos, values);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... values) {
- final MethodHandle mh = super.dropArguments(target, pos, values);
+ final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
return debug(mh, "dropArguments", target, pos, values);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> values) {
- final MethodHandle mh = super.dropArguments(target, pos, values);
+ final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
return debug(mh, "dropArguments", target, pos, values);
}
@Override
public MethodHandle asType(final MethodHandle handle, final MethodType type) {
- final MethodHandle mh = super.asType(handle, type);
+ final MethodHandle mh = handle.asType(type);
return debug(mh, "asType", handle, type);
}
@Override
public MethodHandle bindTo(final MethodHandle handle, final Object x) {
- final MethodHandle mh = super.bindTo(handle, x);
+ final MethodHandle mh = handle.bindTo(x);
return debug(mh, "bindTo", handle, x);
}
@Override
public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
- final MethodHandle mh = super.foldArguments(target, combiner);
+ final MethodHandle mh = MethodHandles.foldArguments(target, combiner);
return debug(mh, "foldArguments", target, combiner);
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
- final MethodHandle mh = super.explicitCastArguments(target, type);
+ final MethodHandle mh = MethodHandles.explicitCastArguments(target, type);
return debug(mh, "explicitCastArguments", target, type);
}
@Override
public MethodHandle arrayElementGetter(final Class<?> type) {
- final MethodHandle mh = super.arrayElementGetter(type);
+ final MethodHandle mh = MethodHandles.arrayElementGetter(type);
return debug(mh, "arrayElementGetter", type);
}
@Override
public MethodHandle arrayElementSetter(final Class<?> type) {
- final MethodHandle mh = super.arrayElementSetter(type);
+ final MethodHandle mh = MethodHandles.arrayElementSetter(type);
return debug(mh, "arrayElementSetter", type);
}
@Override
public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
- final MethodHandle mh = super.throwException(returnType, exType);
+ final MethodHandle mh = MethodHandles.throwException(returnType, exType);
return debug(mh, "throwException", returnType, exType);
}
@Override
+ public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
+ final MethodHandle mh = MethodHandles.catchException(target, exType, handler);
+ return debug(mh, "catchException", exType);
+ }
+
+ @Override
public MethodHandle constant(final Class<?> type, final Object value) {
- final MethodHandle mh = super.constant(type, value);
+ final MethodHandle mh = MethodHandles.constant(type, value);
return debug(mh, "constant", type, value);
}
@Override
+ public MethodHandle identity(final Class<?> type) {
+ final MethodHandle mh = MethodHandles.identity(type);
+ return debug(mh, "identity", type);
+ }
+
+ @Override
public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
- final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength);
+ final MethodHandle mh = handle.asCollector(arrayType, arrayLength);
return debug(mh, "asCollector", handle, arrayType, arrayLength);
}
@Override
public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
- final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength);
+ final MethodHandle mh = handle.asSpreader(arrayType, arrayLength);
return debug(mh, "asSpreader", handle, arrayType, arrayLength);
}
@Override
public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- final MethodHandle mh = super.getter(explicitLookup, clazz, name, type);
- return debug(mh, "getter", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findGetter(clazz, name, type);
+ return debug(mh, "getter", explicitLookup, clazz, name, type);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- final MethodHandle mh = super.staticGetter(explicitLookup, clazz, name, type);
- return debug(mh, "static getter", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findStaticGetter(clazz, name, type);
+ return debug(mh, "static getter", explicitLookup, clazz, name, type);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- final MethodHandle mh = super.setter(explicitLookup, clazz, name, type);
- return debug(mh, "setter", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findSetter(clazz, name, type);
+ return debug(mh, "setter", explicitLookup, clazz, name, type);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
- final MethodHandle mh = super.staticSetter(explicitLookup, clazz, name, type);
- return debug(mh, "static setter", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findStaticSetter(clazz, name, type);
+ return debug(mh, "static setter", explicitLookup, clazz, name, type);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle find(final Method method) {
- final MethodHandle mh = super.find(method);
- return debug(mh, "find", method);
+ try {
+ final MethodHandle mh = PUBLIC_LOOKUP.unreflect(method);
+ return debug(mh, "find", method);
+ } catch (final IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
- final MethodHandle mh = super.findStatic(explicitLookup, clazz, name, type);
- return debug(mh, "findStatic", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findStatic(clazz, name, type);
+ return debug(mh, "findStatic", explicitLookup, clazz, name, type);
+ } catch (final NoSuchMethodException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
+ }
+
+ @Override
+ public MethodHandle findSpecial(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type, final Class<?> thisClass) {
+ try {
+ final MethodHandle mh = explicitLookup.findSpecial(clazz, name, type, thisClass);
+ return debug(mh, "findSpecial", explicitLookup, clazz, name, type);
+ } catch (final NoSuchMethodException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
- final MethodHandle mh = super.findVirtual(explicitLookup, clazz, name, type);
- return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
+ try {
+ final MethodHandle mh = explicitLookup.findVirtual(clazz, name, type);
+ return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
+ } catch (final NoSuchMethodException | IllegalAccessException e) {
+ throw new LookupException(e);
+ }
}
@Override
public SwitchPoint createSwitchPoint() {
- final SwitchPoint sp = super.createSwitchPoint();
- LOG.log(TRACE_LEVEL, "createSwitchPoint ", sp);
+ final SwitchPoint sp = new SwitchPoint();
+ log.log(TRACE_LEVEL, "createSwitchPoint ", sp);
return sp;
}
@Override
public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
- final MethodHandle mh = super.guardWithTest(sp, before, after);
+ final MethodHandle mh = sp.guardWithTest(before, after);
return debug(mh, "guardWithTest", sp, before, after);
}
@Override
public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
- final MethodType mt = super.type(returnType, paramTypes);
- LOG.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
+ final MethodType mt = MethodType.methodType(returnType, paramTypes);
+ log.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
return mt;
}
}
-
- /**
- * Class used for debugging Nashorn generated method handles
- */
- private static class TraceCreateMethodHandleFunctionality extends TraceMethodHandleFunctionality {
- @Override
- public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
- LOG.log(TRACE_LEVEL, str, " ", describe(args));
- stacktrace(LOG);
- return master;
- }
- }
}
diff --git a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
index c7dd83b2..beaa85c2 100644
--- a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
+++ b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
@@ -152,6 +152,17 @@ public interface MethodHandleFunctionality {
public MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType);
/**
+ * Wrapper for {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
+ *
+ * @param target target method
+ * @param exType exception type
+ * @param handler the method handle to call when exception is thrown
+ *
+ * @return exception thrower method handle
+ */
+ public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler);
+
+ /**
* Wrapper for {@link java.lang.invoke.MethodHandles#constant(Class, Object)}
*
* @param type type of constant
@@ -162,6 +173,15 @@ public interface MethodHandleFunctionality {
public MethodHandle constant(Class<?> type, Object value);
/**
+ * Wrapper for {@link java.lang.invoke.MethodHandles#identity(Class)}
+ *
+ * @param type type of value
+ *
+ * @return method handle that returns identity argument
+ */
+ public MethodHandle identity(Class<?> type);
+
+ /**
* Wrapper for {@link java.lang.invoke.MethodHandle#asType(MethodType)}
*
* @param handle method handle for type conversion
@@ -286,6 +306,19 @@ public interface MethodHandleFunctionality {
public MethodHandle findVirtual(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type);
/**
+ * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)}
+ *
+ * @param explicitLookup explicit lookup to be used
+ * @param clazz class to look in
+ * @param name name of method
+ * @param type method type
+ * @param thisClass thisClass
+ *
+ * @return method handle for virtual method
+ */
+ public MethodHandle findSpecial(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type, final Class<?> thisClass);
+
+ /**
* Wrapper for SwitchPoint creation. Just like {@code new SwitchPoint()} but potentially
* tracked
*
@@ -313,5 +346,6 @@ public interface MethodHandleFunctionality {
* @return the method type
*/
public MethodType type(Class<?> returnType, Class<?>... paramTypes);
+
}
diff --git a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index e39c5217..0e8ed350 100644
--- a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -209,6 +209,11 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " getter=" + get + " setter=" + set + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 7;
hash = 41 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index c29af851..fa3b8071 100644
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -26,7 +26,13 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
-
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -35,33 +41,56 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
+/**
+ * ArrayBufferView, es6 class or TypedArray implementation
+ */
@ScriptClass("ArrayBufferView")
-abstract class ArrayBufferView extends ScriptObject {
+public abstract class ArrayBufferView extends ScriptObject {
+ private final NativeArrayBuffer buffer;
+ private final int byteOffset;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
super($nasgenmap$);
- checkConstructorArgs(buffer, byteOffset, elementLength);
- this.setProto(getPrototype(global));
- this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
+
+ final int bytesPerElement = bytesPerElement();
+
+ checkConstructorArgs(buffer.getByteLength(), bytesPerElement, byteOffset, elementLength);
+ setProto(getPrototype(global));
+
+ this.buffer = buffer;
+ this.byteOffset = byteOffset;
+
+ assert byteOffset % bytesPerElement == 0;
+ final int start = byteOffset / bytesPerElement;
+ final ByteBuffer newNioBuffer = buffer.getNioBuffer().duplicate().order(ByteOrder.nativeOrder());
+ final ArrayData data = factory().createArrayData(newNioBuffer, start, start + elementLength);
+
+ setArray(data);
}
- ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+ /**
+ * Constructor
+ *
+ * @param buffer underlying NativeArrayBuffer
+ * @param byteOffset byte offset for buffer
+ * @param elementLength element length in bytes
+ */
+ protected ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
this(buffer, byteOffset, elementLength, Global.instance());
}
- private void checkConstructorArgs(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+ private static void checkConstructorArgs(final int byteLength, final int bytesPerElement, final int byteOffset, final int elementLength) {
if (byteOffset < 0 || elementLength < 0) {
- throw new RuntimeException("byteOffset or length must not be negative");
- }
- if (byteOffset + elementLength * bytesPerElement() > buffer.getByteLength()) {
- throw new RuntimeException("byteOffset + byteLength out of range");
- }
- if (byteOffset % bytesPerElement() != 0) {
- throw new RuntimeException("byteOffset must be a multiple of the element size");
+ throw new RuntimeException("byteOffset or length must not be negative, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+ } else if (byteOffset + elementLength * bytesPerElement > byteLength) {
+ throw new RuntimeException("byteOffset + byteLength out of range, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+ } else if (byteOffset % bytesPerElement != 0) {
+ throw new RuntimeException("byteOffset must be a multiple of the element size, byteOffset=" + byteOffset + " bytesPerElement=" + bytesPerElement);
}
}
@@ -69,24 +98,44 @@ abstract class ArrayBufferView extends ScriptObject {
return factory().bytesPerElement;
}
+ /**
+ * Buffer getter as per spec
+ * @param self ArrayBufferView instance
+ * @return buffer
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static Object buffer(final Object self) {
- return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
+ return ((ArrayBufferView)self).buffer;
}
+ /**
+ * Buffer offset getter as per spec
+ * @param self ArrayBufferView instance
+ * @return buffer offset
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteOffset(final Object self) {
- return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).byteOffset;
+ public static int byteOffset(final Object self) {
+ return ((ArrayBufferView)self).byteOffset;
}
+ /**
+ * Byte length getter as per spec
+ * @param self ArrayBufferView instance
+ * @return array buffer view length in bytes
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteLength(final Object self) {
+ public static int byteLength(final Object self) {
final ArrayBufferView view = (ArrayBufferView)self;
- return ((ArrayDataImpl)view.getArray()).elementLength * view.bytesPerElement();
+ return ((TypedArrayData<?>)view.getArray()).getElementLength() * view.bytesPerElement();
}
+ /**
+ * Length getter as per spec
+ * @param self ArrayBufferView instance
+ * @return length in elements
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object length(final Object self) {
+ public static int length(final Object self) {
return ((ArrayBufferView)self).elementLength();
}
@@ -96,221 +145,119 @@ abstract class ArrayBufferView extends ScriptObject {
}
private int elementLength() {
- return ((ArrayDataImpl)getArray()).elementLength;
- }
-
- protected static abstract class ArrayDataImpl extends ArrayData {
- protected final NativeArrayBuffer buffer;
- protected final int byteOffset;
- private final int elementLength;
-
- protected ArrayDataImpl(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(elementLength);
- this.buffer = buffer;
- this.byteOffset = byteOffset;
- this.elementLength = elementLength;
- }
-
- @Override
- public ArrayData copy() {
- throw new UnsupportedOperationException(); // Not used for ArrayBuffers
- }
-
- @Override
- public Object[] asObjectArray() {
- final Object[] array = new Object[elementLength];
- for (int i = 0; i < elementLength; i++) {
- array[i] = getObjectImpl(i);
- }
- return array;
- }
-
- @Override
- public ArrayData ensure(final long safeIndex) {
- return this;
- }
-
- @Override
- public void setLength(final long length) {
- //empty?
- //TODO is this right?
- }
-
- @Override
- public ArrayData shrink(final long newLength) {
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final Object value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final int value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final double value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public int getInt(final int index) {
- return getIntImpl(index);
- }
-
- @Override
- public long getLong(final int index) {
- return getLongImpl(index);
- }
-
- @Override
- public double getDouble(final int index) {
- return getDoubleImpl(index);
- }
-
- @Override
- public Object getObject(final int index) {
- return getObjectImpl(index);
- }
-
- @Override
- public boolean has(final int index) {
- return index >= 0 && index < elementLength;
- }
-
- @Override
- public boolean canDelete(final int index, final boolean strict) {
- return false;
- }
-
- @Override
- public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
- return false;
- }
-
- @Override
- public ArrayData delete(final int index) {
- return this;
- }
-
- @Override
- public ArrayData delete(final long fromIndex, final long toIndex) {
- return this;
- }
-
- @Override
- protected ArrayData convert(final Class<?> type) {
- return this;
- }
-
- @Override
- public void shiftLeft(final int by) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ArrayData shiftRight(final int by) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object pop() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ArrayData slice(final long from, final long to) {
- throw new UnsupportedOperationException();
- }
-
- protected abstract int getIntImpl(int key);
-
- protected long getLongImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected double getDoubleImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected Object getObjectImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected abstract void setImpl(int key, int value);
-
- protected void setImpl(final int key, final long value) {
- setImpl(key, (int)value);
- }
-
- protected void setImpl(final int key, final double value) {
- setImpl(key, JSType.toInt32(value));
- }
-
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toInt32(value));
- }
-
- protected abstract int byteIndex(int index);
+ return ((TypedArrayData<?>)getArray()).getElementLength();
}
+ /**
+ * Factory class for byte ArrayBufferViews
+ */
protected static abstract class Factory {
final int bytesPerElement;
final int maxElementLength;
+ /**
+ * Constructor
+ *
+ * @param bytesPerElement number of bytes per element for this buffer
+ */
public Factory(final int bytesPerElement) {
- this.bytesPerElement = bytesPerElement;
+ this.bytesPerElement = bytesPerElement;
this.maxElementLength = Integer.MAX_VALUE / bytesPerElement;
}
+ /**
+ * Factory method
+ *
+ * @param elementLength number of elements
+ * @return new ArrayBufferView
+ */
public final ArrayBufferView construct(final int elementLength) {
- if(elementLength > maxElementLength) {
+ if (elementLength > maxElementLength) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(elementLength));
}
return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength);
}
- public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength);
-
- public abstract ArrayData createArrayData(NativeArrayBuffer buffer, int byteOffset, int elementLength);
+ /**
+ * Factory method
+ *
+ * @param buffer underlying buffer
+ * @param byteOffset byte offset
+ * @param elementLength number of elements
+ *
+ * @return new ArrayBufferView
+ */
+ public abstract ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength);
+
+ /**
+ * Factory method for array data
+ *
+ * @param nb underlying nativebuffer
+ * @param start start element
+ * @param end end element
+ *
+ * @return new array data
+ */
+ public abstract TypedArrayData<?> createArrayData(final ByteBuffer nb, final int start, final int end);
+
+ /**
+ * Get the class name for this type of buffer
+ *
+ * @return class name
+ */
+ public abstract String getClassName();
}
+ /**
+ * Get the factor for this kind of buffer
+ * @return Factory
+ */
protected abstract Factory factory();
+ /**
+ * Get the prototype for this ArrayBufferView
+ * @param global global instance
+ * @return prototype
+ */
protected abstract ScriptObject getPrototype(final Global global);
+ @Override
+ public final String getClassName() {
+ return factory().getClassName();
+ }
+
+ /**
+ * Check if this array contains floats
+ * @return true if float array (or double)
+ */
protected boolean isFloatArray() {
return false;
}
- protected static ArrayBufferView constructorImpl(final Object[] args, final Factory factory) {
- final Object arg0 = args.length != 0 ? args[0] : 0;
- final ArrayBufferView dst;
- final int length;
+ /**
+ * Inheritable constructor implementation
+ *
+ * @param newObj is this a new constructor
+ * @param args arguments
+ * @param factory factory
+ *
+ * @return new ArrayBufferView
+ */
+ protected static ArrayBufferView constructorImpl(final boolean newObj, final Object[] args, final Factory factory) {
+ final Object arg0 = args.length != 0 ? args[0] : 0;
+ final ArrayBufferView dest;
+ final int length;
+
+ if (!newObj) {
+ throw typeError("constructor.requires.new", factory.getClassName());
+ }
+
+
if (arg0 instanceof NativeArrayBuffer) {
// Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length)
- final NativeArrayBuffer buffer = (NativeArrayBuffer) arg0;
- final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+ final NativeArrayBuffer buffer = (NativeArrayBuffer)arg0;
+ final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+
if (args.length > 2) {
length = JSType.toInt32(args[2]);
} else {
@@ -319,27 +266,39 @@ abstract class ArrayBufferView extends ScriptObject {
}
length = (buffer.getByteLength() - byteOffset) / factory.bytesPerElement;
}
+
return factory.construct(buffer, byteOffset, length);
} else if (arg0 instanceof ArrayBufferView) {
// Constructor(TypedArray array)
length = ((ArrayBufferView)arg0).elementLength();
- dst = factory.construct(length);
+ dest = factory.construct(length);
} else if (arg0 instanceof NativeArray) {
// Constructor(type[] array)
length = lengthToInt(((NativeArray) arg0).getArray().length());
- dst = factory.construct(length);
+ dest = factory.construct(length);
} else {
- // Constructor(unsigned long length)
- length = lengthToInt(JSType.toInt64(arg0));
+ // Constructor(unsigned long length). Treating infinity as 0 is a special case for ArrayBufferView.
+ final double dlen = JSType.toNumber(arg0);
+ length = lengthToInt(Double.isInfinite(dlen) ? 0L : JSType.toLong(dlen));
return factory.construct(length);
}
- copyElements(dst, length, (ScriptObject)arg0, 0);
- return dst;
+ copyElements(dest, length, (ScriptObject)arg0, 0);
+
+ return dest;
}
+ /**
+ * Inheritable implementation of set, if no efficient implementation is available
+ *
+ * @param self ArrayBufferView instance
+ * @param array array
+ * @param offset0 array offset
+ *
+ * @return result of setter
+ */
protected static Object setImpl(final Object self, final Object array, final Object offset0) {
- final ArrayBufferView dest = ((ArrayBufferView)self);
+ final ArrayBufferView dest = (ArrayBufferView)self;
final int length;
if (array instanceof ArrayBufferView) {
// void set(TypedArray array, optional unsigned long offset)
@@ -351,7 +310,7 @@ abstract class ArrayBufferView extends ScriptObject {
throw new RuntimeException("argument is not of array type");
}
- final ScriptObject source = (ScriptObject) array;
+ final ScriptObject source = (ScriptObject)array;
final int offset = JSType.toInt32(offset0); // default=0
if (dest.elementLength() < length + offset || offset < 0) {
@@ -366,11 +325,11 @@ abstract class ArrayBufferView extends ScriptObject {
private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
if (!dest.isFloatArray()) {
for (int i = 0, j = offset; i < length; i++, j++) {
- dest.set(j, source.getInt(i), false);
+ dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), 0);
}
} else {
for (int i = 0, j = offset; i < length; i++, j++) {
- dest.set(j, source.getDouble(i), false);
+ dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), 0);
}
}
}
@@ -379,15 +338,48 @@ abstract class ArrayBufferView extends ScriptObject {
if (length > Integer.MAX_VALUE || length < 0) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(length));
}
- return (int) (length & Integer.MAX_VALUE);
+ return (int)(length & Integer.MAX_VALUE);
}
+ /**
+ * Implementation of subarray if no efficient override exists
+ *
+ * @param self ArrayBufferView instance
+ * @param begin0 begin index
+ * @param end0 end index
+ *
+ * @return sub array
+ */
protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
- final ArrayBufferView arrayView = ((ArrayBufferView)self);
- final int elementLength = arrayView.elementLength();
- final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
- final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
- final ArrayDataImpl arrayData = (ArrayDataImpl)arrayView.getArray();
- return arrayView.factory().construct(arrayData.buffer, arrayData.byteIndex(begin), Math.max(end - begin, 0));
+ final ArrayBufferView arrayView = (ArrayBufferView)self;
+ final int byteOffset = arrayView.byteOffset;
+ final int bytesPerElement = arrayView.bytesPerElement();
+ final int elementLength = arrayView.elementLength();
+ final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
+ final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
+ final int length = Math.max(end - begin, 0);
+
+ assert byteOffset % bytesPerElement == 0;
+
+ //second is byteoffset
+ return arrayView.factory().construct(arrayView.buffer, begin * bytesPerElement + byteOffset, length);
+ }
+
+ @Override
+ protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetIndexMethod(desc, request);
+ }
+
+ @Override
+ protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findSetIndexMethod(desc, request);
}
}
diff --git a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
index d0e5b987..333790f2 100644
--- a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
+++ b/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
@@ -38,7 +38,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
final class BoundScriptFunctionImpl extends ScriptFunctionImpl {
private final ScriptFunction targetFunction;
- BoundScriptFunctionImpl(ScriptFunctionData data, ScriptFunction targetFunction) {
+ BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) {
super(data, Global.instance());
setPrototype(ScriptRuntime.UNDEFINED);
this.targetFunction = targetFunction;
diff --git a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index e117c7ed..24722930 100644
--- a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -197,6 +197,11 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " writable=" + writable + " value=" + value + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index 19cc8b6f..39d0b3ec 100644
--- a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -176,6 +176,11 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java
index 0614c4b4..bb3e13d2 100644
--- a/src/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk/nashorn/internal/objects/Global.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -33,20 +34,30 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.api.scripting.ClassFilter;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.GlobalConstants;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
@@ -55,13 +66,14 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
+import jdk.nashorn.internal.runtime.Specialization;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.regexp.RegExpResult;
import jdk.nashorn.internal.scripts.JO;
@@ -70,9 +82,35 @@ import jdk.nashorn.internal.scripts.JO;
*/
@ScriptClass("Global")
public final class Global extends ScriptObject implements Scope {
+ // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
+ private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
+ /**
+ * Optimistic builtin names that require switchpoint invalidation
+ * upon assignment. Overly conservative, but works for now, to avoid
+ * any complicated scope checks and especially heavy weight guards
+ * like
+ *
+ * <pre>
+ * public boolean setterGuard(final Object receiver) {
+ * final Global global = Global.instance();
+ * final ScriptObject sobj = global.getFunctionPrototype();
+ * final Object apply = sobj.get("apply");
+ * return apply == receiver;
+ * }
+ * </pre>
+ *
+ * Naturally, checking for builtin classes like NativeFunction is cheaper,
+ * it's when you start adding property checks for said builtins you have
+ * problems with guard speed.
+ */
+
+ /** Nashorn extension: arguments array */
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
+ public Object arguments;
+
/** ECMA 15.1.2.2 parseInt (string , radix) */
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object parseInt;
@@ -135,11 +173,11 @@ public final class Global extends ScriptObject implements Scope {
/** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public final Object NaN = Double.NaN;
+ public final double NaN = Double.NaN;
/** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public final Object Infinity = Double.POSITIVE_INFINITY;
+ public final double Infinity = Double.POSITIVE_INFINITY;
/** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
@@ -303,15 +341,15 @@ public final class Global extends ScriptObject implements Scope {
/** Nashorn extension: current script's file name */
@Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __FILE__;
+ public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Nashorn extension: current script's directory */
@Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __DIR__;
+ public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Nashorn extension: current source line number being executed */
@Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __LINE__;
+ public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Used as Date.prototype's default value */
public NativeDate DEFAULT_DATE;
@@ -352,19 +390,19 @@ public final class Global extends ScriptObject implements Scope {
private ScriptObject builtinJavafx;
private ScriptObject builtinJavax;
private ScriptObject builtinOrg;
- private ScriptObject builtinJavaImporter;
+ private ScriptFunction builtinJavaImporter;
private ScriptObject builtinJavaApi;
- private ScriptObject builtinArrayBuffer;
- private ScriptObject builtinDataView;
- private ScriptObject builtinInt8Array;
- private ScriptObject builtinUint8Array;
- private ScriptObject builtinUint8ClampedArray;
- private ScriptObject builtinInt16Array;
- private ScriptObject builtinUint16Array;
- private ScriptObject builtinInt32Array;
- private ScriptObject builtinUint32Array;
- private ScriptObject builtinFloat32Array;
- private ScriptObject builtinFloat64Array;
+ private ScriptFunction builtinArrayBuffer;
+ private ScriptFunction builtinDataView;
+ private ScriptFunction builtinInt8Array;
+ private ScriptFunction builtinUint8Array;
+ private ScriptFunction builtinUint8ClampedArray;
+ private ScriptFunction builtinInt16Array;
+ private ScriptFunction builtinUint16Array;
+ private ScriptFunction builtinInt32Array;
+ private ScriptFunction builtinUint32Array;
+ private ScriptFunction builtinFloat32Array;
+ private ScriptFunction builtinFloat64Array;
/*
* ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
@@ -377,12 +415,14 @@ public final class Global extends ScriptObject implements Scope {
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
- private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
- private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
- private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
- private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
- private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
- private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
+ private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
+ private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
+ private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
+ private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
+ private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
+ private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
+ private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
+ private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
// initialized by nasgen
private static PropertyMap $nasgenmap$;
@@ -390,6 +430,25 @@ public final class Global extends ScriptObject implements Scope {
// context to which this global belongs to
private final Context context;
+ // current ScriptContext to use - can be null.
+ private ScriptContext scontext;
+ // current ScriptEngine associated - can be null.
+ private ScriptEngine engine;
+
+ // ES6 global lexical scope.
+ private final LexicalScope lexicalScope;
+
+ // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
+ private SwitchPoint lexicalScopeSwitchPoint;
+
+ /**
+ * Set the current script context
+ * @param scontext script context
+ */
+ public void setScriptContext(final ScriptContext scontext) {
+ this.scontext = scontext;
+ }
+
@Override
protected Context getContext() {
return context;
@@ -407,12 +466,7 @@ public final class Global extends ScriptObject implements Scope {
// null check on context
context.getClass();
- /*
- * Duplicate global's map and use it. This way the initial Map filled
- * by nasgen (referenced from static field in this class) is retained
- * 'as is' (as that one is process wide singleton.
- */
- return $nasgenmap$.duplicate();
+ return $nasgenmap$;
}
/**
@@ -424,6 +478,7 @@ public final class Global extends ScriptObject implements Scope {
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
+ this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
}
/**
@@ -432,11 +487,23 @@ public final class Global extends ScriptObject implements Scope {
* @return the global singleton
*/
public static Global instance() {
- Global global = Context.getGlobal();
+ final Global global = Context.getGlobal();
global.getClass(); // null check
return global;
}
+ private static Global instanceFrom(final Object self) {
+ return self instanceof Global? (Global)self : instance();
+ }
+
+ /**
+ * Check if we have a Global instance
+ * @return true if one exists
+ */
+ public static boolean hasInstance() {
+ return Context.getGlobal() != null;
+ }
+
/**
* Script access to {@link ScriptEnvironment}
*
@@ -458,6 +525,14 @@ public final class Global extends ScriptObject implements Scope {
// Runtime interface to Global
/**
+ * Is there a class filter in the current Context?
+ * @return class filter
+ */
+ public ClassFilter getClassFilter() {
+ return context.getClassFilter();
+ }
+
+ /**
* Is this global of the given Context?
* @param ctxt the context
* @return true if this global belongs to the given Context
@@ -478,28 +553,18 @@ public final class Global extends ScriptObject implements Scope {
* Initialize standard builtin objects like "Object", "Array", "Function" etc.
* as well as our extension builtin objects like "Java", "JSAdapter" as properties
* of the global scope object.
+ *
+ * @param engine ScriptEngine to initialize
*/
- public void initBuiltinObjects() {
+ @SuppressWarnings("hiding")
+ public void initBuiltinObjects(final ScriptEngine engine) {
if (this.builtinObject != null) {
// already initialized, just return
return;
}
- init();
- }
-
- /**
- * Create a new ScriptFunction object
- *
- * @param name function name
- * @param handle invocation handle for function
- * @param scope the scope
- * @param strict are we in strict mode
- *
- * @return new script function
- */
- public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
- return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
+ this.engine = engine;
+ init(engine);
}
/**
@@ -537,7 +602,7 @@ public final class Global extends ScriptObject implements Scope {
*
* @return guarded invocation
*/
- public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
+ public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
if (self instanceof String || self instanceof ConsString) {
return NativeString.lookupPrimitive(request, self);
} else if (self instanceof Number) {
@@ -549,6 +614,24 @@ public final class Global extends ScriptObject implements Scope {
}
/**
+ * Returns a method handle that creates a wrapper object for a JS primitive value.
+ *
+ * @param self receiver object
+ * @return method handle to create wrapper objects for primitive receiver
+ */
+ public static MethodHandle getPrimitiveWrapFilter(final Object self) {
+ if (self instanceof String || self instanceof ConsString) {
+ return NativeString.WRAPFILTER;
+ } else if (self instanceof Number) {
+ return NativeNumber.WRAPFILTER;
+ } else if (self instanceof Boolean) {
+ return NativeBoolean.WRAPFILTER;
+ }
+ throw new IllegalArgumentException("Unsupported primitive: " + self);
+ }
+
+
+ /**
* Create a new empty script object
*
* @return the new ScriptObject
@@ -729,6 +812,7 @@ public final class Global extends ScriptObject implements Scope {
* @param value of the data property
* @param configurable is the property configurable?
* @param enumerable is the property enumerable?
+ * @param writable is the property writable?
* @return newly created DataPropertyDescriptor object
*/
public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
@@ -758,7 +842,6 @@ public final class Global extends ScriptObject implements Scope {
return desc;
}
-
private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
final T obj = map.get(key);
if (obj != null) {
@@ -800,6 +883,41 @@ public final class Global extends ScriptObject implements Scope {
}
/**
+ * Hook to search missing variables in ScriptContext if available
+ * @param self used to detect if scope call or not (this function is 'strict')
+ * @param name name of the variable missing
+ * @return value of the missing variable or undefined (or TypeError for scope search)
+ */
+ public static Object __noSuchProperty__(final Object self, final Object name) {
+ final Global global = Global.instance();
+ final ScriptContext sctxt = global.scontext;
+ final String nameStr = name.toString();
+
+ if (sctxt != null) {
+ final int scope = sctxt.getAttributesScope(nameStr);
+ if (scope != -1) {
+ return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
+ }
+ }
+
+ switch (nameStr) {
+ case "context":
+ return sctxt;
+ case "engine":
+ return global.engine;
+ default:
+ break;
+ }
+
+ if (self == UNDEFINED) {
+ // scope access and so throw ReferenceError
+ throw referenceError(global, "not.defined", nameStr);
+ }
+
+ return UNDEFINED;
+ }
+
+ /**
* This is the eval used when 'indirect' eval call is made.
*
* var global = this;
@@ -811,7 +929,7 @@ public final class Global extends ScriptObject implements Scope {
* @return the result of eval
*/
public static Object eval(final Object self, final Object str) {
- return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
+ return directEval(self, str, UNDEFINED, UNDEFINED, false);
}
/**
@@ -827,14 +945,14 @@ public final class Global extends ScriptObject implements Scope {
*
* This is directly invoked from generated when eval(code) is called in user code
*/
- public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
+ public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
if (!(str instanceof String || str instanceof ConsString)) {
return str;
}
- final Global global = Global.instance();
- final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+ final Global global = Global.instanceFrom(self);
+ final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
- return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
+ return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
}
/**
@@ -846,7 +964,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of print (undefined)
*/
public static Object print(final Object self, final Object... objects) {
- return printImpl(false, objects);
+ return Global.instanceFrom(self).printImpl(false, objects);
}
/**
@@ -858,7 +976,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of println (undefined)
*/
public static Object println(final Object self, final Object... objects) {
- return printImpl(true, objects);
+ return Global.instanceFrom(self).printImpl(true, objects);
}
/**
@@ -872,8 +990,8 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object load(final Object self, final Object source) throws IOException {
- final Global global = Global.instance();
- final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+ final Global global = Global.instanceFrom(self);
+ final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
return global.getContext().load(scope, source);
}
@@ -888,7 +1006,7 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
- final Global global = Global.instance();
+ final Global global = Global.instanceFrom(self);
final int length = args.length;
final boolean hasArgs = 0 < length;
final Object from = hasArgs ? args[0] : UNDEFINED;
@@ -903,7 +1021,7 @@ public final class Global extends ScriptObject implements Scope {
* @param self self reference
* @param code exit code
*
- * @return undefined (will never be reacheD)
+ * @return undefined (will never be reached)
*/
public static Object exit(final Object self, final Object code) {
System.exit(JSType.toInt32(code));
@@ -1111,6 +1229,40 @@ public final class Global extends ScriptObject implements Scope {
return instance.function == instance.getBuiltinFunction();
}
+ /**
+ * Get the switchpoint used to check property changes for Function.prototype.apply
+ * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
+ */
+ public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
+ return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
+ }
+
+ private static boolean isBuiltinFunctionProperty(final String name) {
+ final Global instance = Global.instance();
+ final ScriptFunction builtinFunction = instance.getBuiltinFunction();
+ if (builtinFunction == null) {
+ return false; //conservative for compile-only mode
+ }
+ final boolean isBuiltinFunction = instance.function == builtinFunction;
+ return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
+ }
+
+ /**
+ * Check if the Function.prototype.apply has not been replaced
+ * @return true if Function.prototype.apply has been replaced
+ */
+ public static boolean isBuiltinFunctionPrototypeApply() {
+ return isBuiltinFunctionProperty("apply");
+ }
+
+ /**
+ * Check if the Function.prototype.apply has not been replaced
+ * @return true if Function.prototype.call has been replaced
+ */
+ public static boolean isBuiltinFunctionPrototypeCall() {
+ return isBuiltinFunctionProperty("call");
+ }
+
private ScriptFunction getBuiltinJSAdapter() {
return builtinJSAdapter;
}
@@ -1457,6 +1609,26 @@ public final class Global extends ScriptObject implements Scope {
}
/**
+ * Called from generated to replace a location property placeholder with the actual location property value.
+ *
+ * @param placeholder the value tested for being a placeholder for a location property
+ * @param locationProperty the actual value for the location property
+ * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
+ */
+ public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
+ return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
+ }
+
+ /**
+ * Called from runtime internals to check if the passed value is a location property placeholder.
+ * @param placeholder the value tested for being a placeholder for a location property
+ * @return true if the value is a placeholder, false otherwise.
+ */
+ public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
+ return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+ }
+
+ /**
* Create a new RegExp object.
*
* @param expression Regular expression.
@@ -1494,11 +1666,13 @@ public final class Global extends ScriptObject implements Scope {
* not the case
*
* @param obj and object to check
+ * @return the script object
*/
- public static void checkObject(final Object obj) {
+ public static ScriptObject checkObject(final Object obj) {
if (!(obj instanceof ScriptObject)) {
throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
}
+ return (ScriptObject)obj;
}
/**
@@ -1533,7 +1707,141 @@ public final class Global extends ScriptObject implements Scope {
splitState = state;
}
- private void init() {
+ /**
+ * Return the ES6 global scope for lexically declared bindings.
+ * @return the ES6 lexical global scope.
+ */
+ public final ScriptObject getLexicalScope() {
+ assert context.getEnv()._es6;
+ return lexicalScope;
+ }
+
+ @Override
+ public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
+ PropertyMap ownMap = getMap();
+ LexicalScope lexicalScope = null;
+ PropertyMap lexicalMap = null;
+ boolean hasLexicalDefinitions = false;
+
+ if (context.getEnv()._es6) {
+ lexicalScope = (LexicalScope) getLexicalScope();
+ lexicalMap = lexicalScope.getMap();
+
+ for (final jdk.nashorn.internal.runtime.Property property : properties) {
+ if (property.isLexicalBinding()) {
+ hasLexicalDefinitions = true;
+ }
+ // ES6 15.1.8 steps 6. and 7.
+ final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
+ if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
+ throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
+ }
+ final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
+ if (lexicalProperty != null && !property.isConfigurable()) {
+ throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
+ }
+ }
+ }
+
+ for (final jdk.nashorn.internal.runtime.Property property : properties) {
+ if (property.isLexicalBinding()) {
+ assert lexicalScope != null;
+ lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
+
+ if (ownMap.findProperty(property.getKey()) != null) {
+ // If property exists in the global object invalidate any global constant call sites.
+ invalidateGlobalConstant(property.getKey());
+ }
+ } else {
+ ownMap = addBoundProperty(ownMap, source, property);
+ }
+ }
+
+ setMap(ownMap);
+
+ if (hasLexicalDefinitions) {
+ lexicalScope.setMap(lexicalMap);
+ invalidateLexicalSwitchPoint();
+ }
+ }
+
+ @Override
+ public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
+
+ if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
+ if (lexicalScope.hasOwnProperty(name)) {
+ return lexicalScope.findGetMethod(desc, request, operator);
+ }
+ }
+
+ final GuardedInvocation invocation = super.findGetMethod(desc, request, operator);
+
+ // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
+ // because those are invalidated per-key in the addBoundProperties method above.
+ // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
+ // assuming this only applies to global constants. If other non-inherited properties will
+ // start using switchpoints some time in the future we'll have to revisit this.
+ if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
+ return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
+ }
+
+ return invocation;
+ }
+
+ @Override
+ public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
+
+ if (lexicalScope != null && isScope) {
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ if (lexicalScope.hasOwnProperty(name)) {
+ return lexicalScope.findSetMethod(desc, request);
+ }
+ }
+
+ final GuardedInvocation invocation = super.findSetMethod(desc, request);
+
+ if (isScope && context.getEnv()._es6) {
+ return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
+ }
+
+ return invocation;
+ }
+
+ private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
+ SwitchPoint switchPoint = lexicalScopeSwitchPoint;
+ if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
+ switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
+ }
+ return switchPoint;
+ }
+
+ private synchronized void invalidateLexicalSwitchPoint() {
+ if (lexicalScopeSwitchPoint != null) {
+ context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
+ SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
+ }
+ }
+
+
+ @SuppressWarnings("unused")
+ private static Object lexicalScopeFilter(final Object self) {
+ if (self instanceof Global) {
+ return ((Global) self).getLexicalScope();
+ }
+ return self;
+ }
+
+ private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
+ final T func = initConstructor(name, clazz);
+ tagBuiltinProperties(name, func);
+ return func;
+ }
+
+ @SuppressWarnings("hiding")
+ private void init(final ScriptEngine engine) {
assert Context.getGlobal() == this : "this global is not set as current";
final ScriptEnvironment env = getContext().getEnv();
@@ -1547,7 +1855,19 @@ public final class Global extends ScriptObject implements Scope {
// initialize global function properties
this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
- this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
+ this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT,
+ new Specialization[] {
+ new Specialization(GlobalFunctions.PARSEINT_Z),
+ new Specialization(GlobalFunctions.PARSEINT_I),
+ new Specialization(GlobalFunctions.PARSEINT_J),
+ new Specialization(GlobalFunctions.PARSEINT_OI),
+ new Specialization(GlobalFunctions.PARSEINT_O) });
+ this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
+ this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN,
+ new Specialization[] {
+ new Specialization(GlobalFunctions.IS_NAN_I),
+ new Specialization(GlobalFunctions.IS_NAN_J),
+ new Specialization(GlobalFunctions.IS_NAN_D) });
this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
@@ -1559,20 +1879,20 @@ public final class Global extends ScriptObject implements Scope {
this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
- this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
+ this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
// built-in constructors
- this.builtinArray = (ScriptFunction)initConstructor("Array");
- this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
- this.builtinDate = (ScriptFunction)initConstructor("Date");
- this.builtinJSON = initConstructor("JSON");
- this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
- this.builtinMath = initConstructor("Math");
- this.builtinNumber = (ScriptFunction)initConstructor("Number");
- this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
- this.builtinString = (ScriptFunction)initConstructor("String");
+ this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
+ this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
+ this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
+ this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
+ this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
+ this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class);
+ this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
+ this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
+ this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class);
// initialize String.prototype.length to 0
// add String.prototype.length
@@ -1632,25 +1952,25 @@ public final class Global extends ScriptObject implements Scope {
copyBuiltins();
- // initialized with strings so that typeof will work as expected.
- this.__FILE__ = "";
- this.__DIR__ = "";
- this.__LINE__ = 0.0;
-
// expose script (command line) arguments as "arguments" property of global
- final List<String> arguments = env.getArguments();
- final Object argsObj = wrapAsObject(arguments.toArray());
-
- addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
+ arguments = wrapAsObject(env.getArguments().toArray());
if (env._scripting) {
// synonym for "arguments" in scripting mode
- addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
+ addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
+ }
+
+ if (engine != null) {
+ // default file name
+ addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
+ // __noSuchProperty__ hook for ScriptContext search of missing variables
+ final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
+ addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
}
}
private void initErrorObjects() {
// Error objects
- this.builtinError = (ScriptFunction)initConstructor("Error");
+ this.builtinError = initConstructor("Error", ScriptFunction.class);
final ScriptObject errorProto = getErrorPrototype();
// Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
@@ -1669,10 +1989,12 @@ public final class Global extends ScriptObject implements Scope {
// ECMA 15.11.4.2 Error.prototype.name
// Error.prototype.name = "Error";
- errorProto.set(NativeError.NAME, "Error", false);
+ errorProto.set(NativeError.NAME, "Error", 0);
// ECMA 15.11.4.3 Error.prototype.message
// Error.prototype.message = "";
- errorProto.set(NativeError.MESSAGE, "", false);
+ errorProto.set(NativeError.MESSAGE, "", 0);
+
+ tagBuiltinProperties("Error", builtinError);
this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
@@ -1683,12 +2005,13 @@ public final class Global extends ScriptObject implements Scope {
}
private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
- final ScriptObject cons = initConstructor(name);
+ final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
- prototype.set(NativeError.NAME, name, false);
- prototype.set(NativeError.MESSAGE, "", false);
+ prototype.set(NativeError.NAME, name, 0);
+ prototype.set(NativeError.MESSAGE, "", 0);
prototype.setInitialProto(errorProto);
- return (ScriptFunction)cons;
+ tagBuiltinProperties(name, cons);
+ return cons;
}
private void initJavaAccess() {
@@ -1700,8 +2023,8 @@ public final class Global extends ScriptObject implements Scope {
this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
this.builtinJavax = new NativeJavaPackage("javax", objectProto);
this.builtinOrg = new NativeJavaPackage("org", objectProto);
- this.builtinJavaImporter = initConstructor("JavaImporter");
- this.builtinJavaApi = initConstructor("Java");
+ this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
+ this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
}
private void initScripting(final ScriptEnvironment scriptEnv) {
@@ -1744,9 +2067,9 @@ public final class Global extends ScriptObject implements Scope {
}
private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
- for (Field f : scriptEnv.getClass().getFields()) {
+ for (final Field f : scriptEnv.getClass().getFields()) {
try {
- options.set(f.getName(), f.get(scriptEnv), false);
+ options.set(f.getName(), f.get(scriptEnv), 0);
} catch (final IllegalArgumentException | IllegalAccessException exp) {
throw new RuntimeException(exp);
}
@@ -1754,17 +2077,18 @@ public final class Global extends ScriptObject implements Scope {
}
private void initTypedArray() {
- this.builtinArrayBuffer = initConstructor("ArrayBuffer");
- this.builtinDataView = initConstructor("DataView");
- this.builtinInt8Array = initConstructor("Int8Array");
- this.builtinUint8Array = initConstructor("Uint8Array");
- this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
- this.builtinInt16Array = initConstructor("Int16Array");
- this.builtinUint16Array = initConstructor("Uint16Array");
- this.builtinInt32Array = initConstructor("Int32Array");
- this.builtinUint32Array = initConstructor("Uint32Array");
- this.builtinFloat32Array = initConstructor("Float32Array");
- this.builtinFloat64Array = initConstructor("Float64Array");
+ this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
+ this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
+ this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
+ this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
+ this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
+ this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
+ this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
+ this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
+ this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
+ this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
+ this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
+
}
private void copyBuiltins() {
@@ -1809,20 +2133,20 @@ public final class Global extends ScriptObject implements Scope {
}
private void initDebug() {
- this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
+ this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
}
- @SuppressWarnings("resource")
- private static Object printImpl(final boolean newLine, final Object... objects) {
- final PrintWriter out = Global.getEnv().getOut();
+ private Object printImpl(final boolean newLine, final Object... objects) {
+ @SuppressWarnings("resource")
+ final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
final StringBuilder sb = new StringBuilder();
- for (final Object object : objects) {
+ for (final Object obj : objects) {
if (sb.length() != 0) {
sb.append(' ');
}
- sb.append(JSType.toString(object));
+ sb.append(JSType.toString(obj));
}
// Print all at once to ensure thread friendly result.
@@ -1837,11 +2161,7 @@ public final class Global extends ScriptObject implements Scope {
return UNDEFINED;
}
- /**
- * These classes are generated by nasgen tool and so we have to use
- * reflection to load and create new instance of these classes.
- */
- private ScriptObject initConstructor(final String name) {
+ private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
try {
// Assuming class name pattern for built-in JS constructors.
final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
@@ -1850,8 +2170,8 @@ public final class Global extends ScriptObject implements Scope {
sb.append(name);
sb.append("$Constructor");
- final Class<?> funcClass = Class.forName(sb.toString());
- final ScriptObject res = (ScriptObject)funcClass.newInstance();
+ final Class<?> funcClass = Class.forName(sb.toString());
+ final T res = clazz.cast(funcClass.newInstance());
if (res instanceof ScriptFunction) {
// All global constructor prototypes are not-writable,
@@ -1864,13 +2184,53 @@ public final class Global extends ScriptObject implements Scope {
res.setInitialProto(getObjectPrototype());
}
- return res;
+ res.setIsBuiltin();
+ return res;
} catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
+ private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
+ final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
+
+ list.addAll(Arrays.asList(func.getMap().getProperties()));
+
+ if (func instanceof ScriptFunction) {
+ final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
+ if (proto != null) {
+ list.addAll(Arrays.asList(proto.getMap().getProperties()));
+ }
+ }
+
+ final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
+ if (prop != null) {
+ list.add(prop);
+ }
+
+ return list;
+ }
+
+ /**
+ * Given a builtin object, traverse its properties recursively and associate them with a name that
+ * will be a key to their invalidation switchpoint.
+ * @param name name for key
+ * @param func builtin script object
+ */
+ private void tagBuiltinProperties(final String name, final ScriptObject func) {
+ SwitchPoint sp = context.getBuiltinSwitchPoint(name);
+ if (sp == null) {
+ sp = context.newBuiltinSwitchPoint(name);
+ }
+
+ //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
+ //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
+ for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
+ prop.setBuiltinSwitchPoint(sp);
+ }
+ }
+
// Function and Object constructors are inter-dependent. Also,
// Function.prototype
// functions are not properly initialized. We fix the references here.
@@ -1879,10 +2239,11 @@ public final class Global extends ScriptObject implements Scope {
// to play with object references carefully!!
private void initFunctionAndObject() {
// First-n-foremost is Function
- this.builtinFunction = (ScriptFunction)initConstructor("Function");
+
+ this.builtinFunction = initConstructor("Function", ScriptFunction.class);
// create global anonymous function
- final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
+ final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
// need to copy over members of Function.prototype to anon function
anon.addBoundProperties(getFunctionPrototype());
@@ -1890,7 +2251,7 @@ public final class Global extends ScriptObject implements Scope {
// <anon-function>
builtinFunction.setInitialProto(anon);
builtinFunction.setPrototype(anon);
- anon.set("constructor", builtinFunction, false);
+ anon.set("constructor", builtinFunction, 0);
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
@@ -1901,7 +2262,7 @@ public final class Global extends ScriptObject implements Scope {
typeErrorThrower.preventExtensions();
// now initialize Object
- this.builtinObject = (ScriptFunction)initConstructor("Object");
+ this.builtinObject = initConstructor("Object", ScriptFunction.class);
final ScriptObject ObjectPrototype = getObjectPrototype();
// Object.getPrototypeOf(Function.prototype) === Object.prototype
anon.setInitialProto(ObjectPrototype);
@@ -1912,7 +2273,6 @@ public final class Global extends ScriptObject implements Scope {
final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
-
// Function valued properties of Function.prototype were not properly
// initialized. Because, these were created before global.function and
// global.object were not initialized.
@@ -1947,14 +2307,14 @@ public final class Global extends ScriptObject implements Scope {
}
properties = getObjectPrototype().getMap().getProperties();
+
for (final jdk.nashorn.internal.runtime.Property property : properties) {
final Object key = property.getKey();
- final Object value = ObjectPrototype.get(key);
-
if (key.equals("constructor")) {
continue;
}
+ final Object value = ObjectPrototype.get(key);
if (value instanceof ScriptFunction) {
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
@@ -1963,9 +2323,13 @@ public final class Global extends ScriptObject implements Scope {
}
}
}
+
+ tagBuiltinProperties("Object", builtinObject);
+ tagBuiltinProperties("Function", builtinFunction);
+ tagBuiltinProperties("Function", anon);
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
}
@@ -1977,4 +2341,40 @@ public final class Global extends ScriptObject implements Scope {
this.lastRegExpResult = regExpResult;
}
+ @Override
+ protected boolean isGlobal() {
+ return true;
+ }
+
+ /**
+ * A class representing the ES6 global lexical scope.
+ */
+ private static class LexicalScope extends ScriptObject {
+
+ LexicalScope(final ScriptObject proto) {
+ super(proto, PropertyMap.newMap());
+ }
+
+ @Override
+ protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+ return filterInvocation(super.findGetMethod(desc, request, operator));
+ }
+
+ @Override
+ protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ return filterInvocation(super.findSetMethod(desc, request));
+ }
+
+ @Override
+ protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
+ // We override this method just to make it callable by Global
+ return super.addBoundProperty(propMap, source, property);
+ }
+
+ private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
+ final MethodType type = invocation.getInvocation().type();
+ return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
+ }
+ }
+
}
diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java
index 6f07cb9d..047d612a 100644
--- a/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,10 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
@@ -41,7 +42,9 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
-
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -49,9 +52,13 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Setter;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.OptimisticBuiltins;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -61,7 +68,11 @@ import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
+import jdk.nashorn.internal.runtime.arrays.ContinuousArrayData;
+import jdk.nashorn.internal.runtime.arrays.IntElements;
+import jdk.nashorn.internal.runtime.arrays.IntOrLongElements;
import jdk.nashorn.internal.runtime.arrays.IteratorAction;
+import jdk.nashorn.internal.runtime.arrays.NumericElements;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -70,7 +81,7 @@ import jdk.nashorn.internal.runtime.linker.InvokeByName;
* keyed values. All other values are stored in spill.
*/
@ScriptClass("Array")
-public final class NativeArray extends ScriptObject {
+public final class NativeArray extends ScriptObject implements OptimisticBuiltins {
private static final Object JOIN = new Object();
private static final Object EVERY_CALLBACK_INVOKER = new Object();
private static final Object SOME_CALLBACK_INVOKER = new Object();
@@ -81,6 +92,89 @@ public final class NativeArray extends ScriptObject {
private static final Object CALL_CMP = new Object();
private static final Object TO_LOCALE_STRING = new Object();
+ /*
+ * Constructors.
+ */
+ NativeArray() {
+ this(ArrayData.initialArray());
+ }
+
+ NativeArray(final long length) {
+ // TODO assert valid index in long before casting
+ this(ArrayData.allocate((int)length));
+ }
+
+ NativeArray(final int[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final long[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final double[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final Object[] array) {
+ this(ArrayData.allocate(array.length));
+
+ ArrayData arrayData = this.getArray();
+ if (array.length > 0) {
+ arrayData.ensure(array.length - 1);
+ }
+
+ for (int index = 0; index < array.length; index++) {
+ final Object value = array[index];
+
+ if (value == ScriptRuntime.EMPTY) {
+ arrayData = arrayData.delete(index);
+ } else {
+ arrayData = arrayData.set(index, value, false);
+ }
+ }
+
+ this.setArray(arrayData);
+ }
+
+ NativeArray(final ArrayData arrayData) {
+ this(arrayData, Global.instance());
+ }
+
+ NativeArray(final ArrayData arrayData, final Global global) {
+ super(global.getArrayPrototype(), $nasgenmap$);
+ setArray(arrayData);
+ setIsArray();
+ }
+
+ @Override
+ protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+ final GuardedInvocation inv = getArray().findFastGetMethod(getArray().getClass(), desc, request, operator);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetMethod(desc, request, operator);
+ }
+
+ @Override
+ protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetIndexMethod(desc, request);
+ }
+
+ @Override
+ protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+
+ return super.findSetIndexMethod(desc, request);
+ }
+
private static InvokeByName getJOIN() {
return Global.instance().getInvokeByName(JOIN,
new Callable<InvokeByName>() {
@@ -157,67 +251,89 @@ public final class NativeArray extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- /*
- * Constructors.
- */
- NativeArray() {
- this(ArrayData.initialArray());
+ @Override
+ public String getClassName() {
+ return "Array";
}
- NativeArray(final long length) {
- // TODO assert valid index in long before casting
- this(ArrayData.allocate((int) length));
+ @Override
+ public Object getLength() {
+ final long length = JSType.toUint32(getArray().length());
+ if (length < Integer.MAX_VALUE) {
+ return (int)length;
+ }
+ return length;
}
- NativeArray(final int[] array) {
- this(ArrayData.allocate(array));
- }
+ private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) {
+ // Step 3a
+ if (!desc.has(VALUE)) {
+ return super.defineOwnProperty("length", desc, reject);
+ }
- NativeArray(final long[] array) {
- this(ArrayData.allocate(array));
- }
+ // Step 3b
+ final PropertyDescriptor newLenDesc = desc;
- NativeArray(final double[] array) {
- this(ArrayData.allocate(array));
- }
+ // Step 3c and 3d - get new length and convert to long
+ final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
- NativeArray(final Object[] array) {
- this(ArrayData.allocate(array.length));
+ // Step 3e
+ newLenDesc.setValue(newLen);
- ArrayData arrayData = this.getArray();
- arrayData.ensure(array.length - 1);
-
- for (int index = 0; index < array.length; index++) {
- final Object value = array[index];
+ // Step 3f
+ // increasing array length - just need to set new length value (and attributes if any) and return
+ if (newLen >= oldLen) {
+ return super.defineOwnProperty("length", newLenDesc, reject);
+ }
- if (value == ScriptRuntime.EMPTY) {
- arrayData = arrayData.delete(index);
- } else {
- arrayData = arrayData.set(index, value, false);
+ // Step 3g
+ if (!oldLenDesc.isWritable()) {
+ if (reject) {
+ throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
}
+ return false;
}
- this.setArray(arrayData);
- }
+ // Step 3h and 3i
+ final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
+ if (!newWritable) {
+ newLenDesc.setWritable(true);
+ }
- NativeArray(final ArrayData arrayData) {
- this(arrayData, Global.instance());
- }
+ // Step 3j and 3k
+ final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
+ if (!succeeded) {
+ return false;
+ }
- NativeArray(final ArrayData arrayData, final Global global) {
- super(global.getArrayPrototype(), $nasgenmap$);
- this.setArray(arrayData);
- this.setIsArray();
- }
+ // Step 3l
+ // make sure that length is set till the point we can delete the old elements
+ long o = oldLen;
+ while (newLen < o) {
+ o--;
+ final boolean deleteSucceeded = delete(o, false);
+ if (!deleteSucceeded) {
+ newLenDesc.setValue(o + 1);
+ if (!newWritable) {
+ newLenDesc.setWritable(false);
+ }
+ super.defineOwnProperty("length", newLenDesc, false);
+ if (reject) {
+ throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
+ }
+ return false;
+ }
+ }
- @Override
- public String getClassName() {
- return "Array";
- }
+ // Step 3m
+ if (!newWritable) {
+ // make 'length' property not writable
+ final ScriptObject newDesc = Global.newEmptyInstance();
+ newDesc.set(WRITABLE, false, 0);
+ return super.defineOwnProperty("length", newDesc, false);
+ }
- @Override
- public Object getLength() {
- return getArray().length() & JSType.MAX_UINT;
+ return true;
}
/**
@@ -233,82 +349,16 @@ public final class NativeArray extends ScriptObject {
// Step 2
// get old length and convert to long
- long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
+ final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
// Step 3
if ("length".equals(key)) {
// check for length being made non-writable
+ final boolean result = defineLength(oldLen, oldLenDesc, desc, reject);
if (desc.has(WRITABLE) && !desc.isWritable()) {
setIsLengthNotWritable();
}
-
- // Step 3a
- if (!desc.has(VALUE)) {
- return super.defineOwnProperty("length", desc, reject);
- }
-
- // Step 3b
- final PropertyDescriptor newLenDesc = desc;
-
- // Step 3c and 3d - get new length and convert to long
- final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
-
- // Step 3e
- newLenDesc.setValue(newLen);
-
- // Step 3f
- // increasing array length - just need to set new length value (and attributes if any) and return
- if (newLen >= oldLen) {
- return super.defineOwnProperty("length", newLenDesc, reject);
- }
-
- // Step 3g
- if (!oldLenDesc.isWritable()) {
- if (reject) {
- throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
- }
- return false;
- }
-
- // Step 3h and 3i
- final boolean newWritable = (!newLenDesc.has(WRITABLE) || newLenDesc.isWritable());
- if (!newWritable) {
- newLenDesc.setWritable(true);
- }
-
- // Step 3j and 3k
- final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
- if (!succeeded) {
- return false;
- }
-
- // Step 3l
- // make sure that length is set till the point we can delete the old elements
- while (newLen < oldLen) {
- oldLen--;
- final boolean deleteSucceeded = delete(oldLen, false);
- if (!deleteSucceeded) {
- newLenDesc.setValue(oldLen + 1);
- if (!newWritable) {
- newLenDesc.setWritable(false);
- }
- super.defineOwnProperty("length", newLenDesc, false);
- if (reject) {
- throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
- }
- return false;
- }
- }
-
- // Step 3m
- if (!newWritable) {
- // make 'length' property not writable
- final ScriptObject newDesc = Global.newEmptyInstance();
- newDesc.set(WRITABLE, false, false);
- return super.defineOwnProperty("length", newDesc, false);
- }
-
- return true;
+ return result;
}
// Step 4a
@@ -381,6 +431,12 @@ public final class NativeArray extends ScriptObject {
return getArray().asObjectArray();
}
+ @Override
+ public void setIsLengthNotWritable() {
+ super.setIsLengthNotWritable();
+ setArray(ArrayData.setIsLengthNotWritable(getArray()));
+ }
+
/**
* ECMA 15.4.3.2 Array.isArray ( arg )
*
@@ -401,7 +457,7 @@ public final class NativeArray extends ScriptObject {
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static Object length(final Object self) {
if (isArray(self)) {
- return ((ScriptObject) self).getArray().length() & JSType.MAX_UINT;
+ return JSType.toUint32(((ScriptObject) self).getArray().length());
}
return 0;
@@ -415,7 +471,7 @@ public final class NativeArray extends ScriptObject {
@Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static void length(final Object self, final Object length) {
if (isArray(self)) {
- ((ScriptObject) self).setLength(validLength(length, true));
+ ((ScriptObject)self).setLength(validLength(length, true));
}
}
@@ -482,6 +538,19 @@ public final class NativeArray extends ScriptObject {
}
/**
+ * Assert that an array is numeric, if not throw type error
+ * @param self self array to check
+ * @return true if numeric
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static Object assertNumeric(final Object self) {
+ if(!(self instanceof NativeArray && ((NativeArray)self).getArray().getOptimisticType().isNumeric())) {
+ throw typeError("not.a.numeric.array", ScriptRuntime.safeToString(self));
+ }
+ return Boolean.TRUE;
+ }
+
+ /**
* ECMA 15.4.4.3 Array.prototype.toLocaleString ( )
*
* @param self self reference
@@ -586,7 +655,7 @@ public final class NativeArray extends ScriptObject {
* @param self self reference
* @return the new NativeArray
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeArray construct(final boolean newObj, final Object self) {
return new NativeArray(0);
}
@@ -594,6 +663,21 @@ public final class NativeArray extends ScriptObject {
/**
* ECMA 15.4.2.2 new Array (len)
*
+ * Specialized constructor for zero arguments - empty array
+ *
+ * @param newObj was the new operator used to instantiate this array
+ * @param self self reference
+ * @param element first element
+ * @return the new NativeArray
+ */
+ @SpecializedFunction(isConstructor=true)
+ public static Object construct(final boolean newObj, final Object self, final boolean element) {
+ return new NativeArray(new Object[] { element });
+ }
+
+ /**
+ * ECMA 15.4.2.2 new Array (len)
+ *
* Specialized constructor for one integer argument (length)
*
* @param newObj was the new operator used to instantiate this array
@@ -601,7 +685,7 @@ public final class NativeArray extends ScriptObject {
* @param length array length
* @return the new NativeArray
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeArray construct(final boolean newObj, final Object self, final int length) {
if (length >= 0) {
return new NativeArray(length);
@@ -620,7 +704,7 @@ public final class NativeArray extends ScriptObject {
* @param length array length
* @return the new NativeArray
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeArray construct(final boolean newObj, final Object self, final long length) {
if (length >= 0L && length <= JSType.MAX_UINT) {
return new NativeArray(length);
@@ -639,7 +723,7 @@ public final class NativeArray extends ScriptObject {
* @param length array length
* @return the new NativeArray
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeArray construct(final boolean newObj, final Object self, final double length) {
final long uint32length = JSType.toUint32(length);
@@ -654,12 +738,86 @@ public final class NativeArray extends ScriptObject {
* ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
*
* @param self self reference
- * @param args arguments to concat
+ * @param arg argument
+ * @return resulting NativeArray
+ */
+ @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+ public static NativeArray concat(final Object self, final int arg) {
+ final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Integer.class).copy(); //get at least an integer data copy of this data
+ newData.fastPush(arg); //add an integer to its end
+ return new NativeArray(newData);
+ }
+
+ /**
+ * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
+ *
+ * @param self self reference
+ * @param arg argument
+ * @return resulting NativeArray
+ */
+ @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+ public static NativeArray concat(final Object self, final long arg) {
+ final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Long.class).copy(); //get at least a long array data copy of this data
+ newData.fastPush(arg); //add a long at the end
+ return new NativeArray(newData);
+ }
+
+ /**
+ * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
+ *
+ * @param self self reference
+ * @param arg argument
+ * @return resulting NativeArray
+ */
+ @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+ public static NativeArray concat(final Object self, final double arg) {
+ final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Double.class).copy(); //get at least a number array data copy of this data
+ newData.fastPush(arg); //add a double at the end
+ return new NativeArray(newData);
+ }
+
+ /**
+ * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
+ *
+ * @param self self reference
+ * @param arg argument
+ * @return resulting NativeArray
+ */
+ @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+ public static NativeArray concat(final Object self, final Object arg) {
+ //arg is [NativeArray] of same type.
+ final ContinuousArrayData selfData = getContinuousArrayDataCCE(self);
+ final ContinuousArrayData newData;
+
+ if (arg instanceof NativeArray) {
+ final ContinuousArrayData argData = (ContinuousArrayData)((NativeArray)arg).getArray();
+ if (argData.isEmpty()) {
+ newData = selfData.copy();
+ } else if (selfData.isEmpty()) {
+ newData = argData.copy();
+ } else {
+ final Class<?> widestElementType = selfData.widest(argData).getBoxedElementType();
+ newData = ((ContinuousArrayData)selfData.convert(widestElementType)).fastConcat((ContinuousArrayData)argData.convert(widestElementType));
+ }
+ } else {
+ newData = getContinuousArrayDataCCE(self, Object.class).copy();
+ newData.fastPush(arg);
+ }
+
+ return new NativeArray(newData);
+ }
+
+ /**
+ * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
+ *
+ * @param self self reference
+ * @param args arguments
* @return resulting NativeArray
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static NativeArray concat(final Object self, final Object... args) {
final ArrayList<Object> list = new ArrayList<>();
+
concatToList(list, Global.toObject(self));
for (final Object obj : args) {
@@ -669,16 +827,16 @@ public final class NativeArray extends ScriptObject {
return new NativeArray(list.toArray());
}
- @SuppressWarnings("null")
private static void concatToList(final ArrayList<Object> list, final Object obj) {
- final boolean isScriptArray = isArray(obj);
+ final boolean isScriptArray = isArray(obj);
final boolean isScriptObject = isScriptArray || obj instanceof ScriptObject;
if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) {
final Iterator<Object> iter = arrayLikeIterator(obj, true);
if (iter.hasNext()) {
for (int i = 0; iter.hasNext(); ++i) {
final Object value = iter.next();
- if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) {
+ final boolean lacksIndex = obj != null && !((ScriptObject)obj).has(i);
+ if (value == ScriptRuntime.UNDEFINED && isScriptObject && lacksIndex) {
// TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling
// UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE,
// RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it
@@ -726,6 +884,68 @@ public final class NativeArray extends ScriptObject {
}
/**
+ * Specialization of pop for ContinuousArrayData
+ * The link guard checks that the array is continuous AND not empty.
+ * The runtime guard checks that the guard is continuous (CCE otherwise)
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @return element popped
+ * @throws ClassCastException if array is empty, facilitating Undefined return value
+ */
+ @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
+ public static int popInt(final Object self) {
+ //must be non empty IntArrayData
+ return getContinuousNonEmptyArrayDataCCE(self, IntElements.class).fastPopInt();
+ }
+
+ /**
+ * Specialization of pop for ContinuousArrayData
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @return element popped
+ * @throws ClassCastException if array is empty, facilitating Undefined return value
+ */
+ @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
+ public static long popLong(final Object self) {
+ //must be non empty Int or LongArrayData
+ return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong();
+ }
+
+ /**
+ * Specialization of pop for ContinuousArrayData
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @return element popped
+ * @throws ClassCastException if array is empty, facilitating Undefined return value
+ */
+ @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
+ public static double popDouble(final Object self) {
+ //must be non empty int long or double array data
+ return getContinuousNonEmptyArrayDataCCE(self, NumericElements.class).fastPopDouble();
+ }
+
+ /**
+ * Specialization of pop for ContinuousArrayData
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @return element popped
+ * @throws ClassCastException if array is empty, facilitating Undefined return value
+ */
+ @SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
+ public static Object popObject(final Object self) {
+ //can be any data, because the numeric ones will throw cce and force relink
+ return getContinuousArrayDataCCE(self, null).fastPopObject();
+ }
+
+ /**
* ECMA 15.4.4.6 Array.prototype.pop ()
*
* @param self self reference
@@ -743,7 +963,7 @@ public final class NativeArray extends ScriptObject {
final long len = JSType.toUint32(sobj.getLength());
if (len == 0) {
- sobj.set("length", 0, true);
+ sobj.set("length", 0, CALLSITE_STRICT);
return ScriptRuntime.UNDEFINED;
}
@@ -751,7 +971,7 @@ public final class NativeArray extends ScriptObject {
final Object element = sobj.get(index);
sobj.delete(index, true);
- sobj.set("length", index, true);
+ sobj.set("length", index, CALLSITE_STRICT);
return element;
} catch (final ClassCastException | NullPointerException e) {
@@ -762,32 +982,112 @@ public final class NativeArray extends ScriptObject {
/**
* ECMA 15.4.4.7 Array.prototype.push (args...)
*
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @param arg a primitive to push
+ * @return array length after push
+ */
+ @SpecializedFunction(linkLogic=PushLinkLogic.class)
+ public static long push(final Object self, final int arg) {
+ return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg);
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...)
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @param arg a primitive to push
+ * @return array length after push
+ */
+ @SpecializedFunction(linkLogic=PushLinkLogic.class)
+ public static long push(final Object self, final long arg) {
+ return getContinuousArrayDataCCE(self, Long.class).fastPush(arg);
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...)
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @param arg a primitive to push
+ * @return array length after push
+ */
+ @SpecializedFunction(linkLogic=PushLinkLogic.class)
+ public static long push(final Object self, final double arg) {
+ return getContinuousArrayDataCCE(self, Double.class).fastPush(arg);
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...)
+ *
+ * Primitive specialization, {@link LinkLogic}
+ *
+ * @param self self reference
+ * @param arg a primitive to push
+ * @return array length after push
+ */
+ @SpecializedFunction(name="push", linkLogic=PushLinkLogic.class)
+ public static long pushObject(final Object self, final Object arg) {
+ return getContinuousArrayDataCCE(self, Object.class).fastPush(arg);
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...)
+ *
* @param self self reference
* @param args arguments to push
- * @return array after pushes
+ * @return array length after pushes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static Object push(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
- if (bulkable(sobj)) {
- if (sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
- final ArrayData newData = sobj.getArray().push(true, args);
- sobj.setArray(newData);
- return newData.length();
- }
- //fallthru
+ if (bulkable(sobj) && sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
+ final ArrayData newData = sobj.getArray().push(true, args);
+ sobj.setArray(newData);
+ return newData.length();
}
long len = JSType.toUint32(sobj.getLength());
for (final Object element : args) {
- sobj.set(len++, element, true);
+ sobj.set(len++, element, CALLSITE_STRICT);
}
- sobj.set("length", len, true);
+ sobj.set("length", len, CALLSITE_STRICT);
return len;
} catch (final ClassCastException | NullPointerException e) {
+ throw typeError(Context.getGlobal(), e, "not.an.object", ScriptRuntime.safeToString(self));
+ }
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single object argument
+ *
+ * @param self self reference
+ * @param arg argument to push
+ * @return array after pushes
+ */
+ @SpecializedFunction
+ public static long push(final Object self, final Object arg) {
+ try {
+ final ScriptObject sobj = (ScriptObject)self;
+ final ArrayData arrayData = sobj.getArray();
+ final long length = arrayData.length();
+ if (bulkable(sobj) && length < JSType.MAX_UINT) {
+ sobj.setArray(arrayData.push(true, arg));
+ return length + 1;
+ }
+
+ long len = JSType.toUint32(sobj.getLength());
+ sobj.set(len++, arg, CALLSITE_STRICT);
+ sobj.set("length", len, CALLSITE_STRICT);
+ return len;
+ } catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
}
}
@@ -813,14 +1113,14 @@ public final class NativeArray extends ScriptObject {
final boolean upperExists = sobj.has(upper);
if (lowerExists && upperExists) {
- sobj.set(lower, upperValue, true);
- sobj.set(upper, lowerValue, true);
+ sobj.set(lower, upperValue, CALLSITE_STRICT);
+ sobj.set(upper, lowerValue, CALLSITE_STRICT);
} else if (!lowerExists && upperExists) {
- sobj.set(lower, upperValue, true);
+ sobj.set(lower, upperValue, CALLSITE_STRICT);
sobj.delete(upper, true);
} else if (lowerExists && !upperExists) {
sobj.delete(lower, true);
- sobj.set(upper, lowerValue, true);
+ sobj.set(upper, lowerValue, CALLSITE_STRICT);
}
}
return sobj;
@@ -857,9 +1157,9 @@ public final class NativeArray extends ScriptObject {
} else {
boolean hasPrevious = true;
for (long k = 1; k < len; k++) {
- boolean hasCurrent = sobj.has(k);
+ final boolean hasCurrent = sobj.has(k);
if (hasCurrent) {
- sobj.set(k - 1, sobj.get(k), true);
+ sobj.set(k - 1, sobj.get(k), CALLSITE_STRICT);
} else if (hasPrevious) {
sobj.delete(k - 1, true);
}
@@ -871,7 +1171,7 @@ public final class NativeArray extends ScriptObject {
len = 0;
}
- sobj.set("length", len, true);
+ sobj.set("length", len, CALLSITE_STRICT);
return first;
}
@@ -894,7 +1194,7 @@ public final class NativeArray extends ScriptObject {
final ScriptObject sobj = (ScriptObject)obj;
final long len = JSType.toUint32(sobj.getLength());
final long relativeStart = JSType.toLong(start);
- final long relativeEnd = (end == ScriptRuntime.UNDEFINED) ? len : JSType.toLong(end);
+ final long relativeEnd = end == ScriptRuntime.UNDEFINED ? len : JSType.toLong(end);
long k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
final long finale = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
@@ -983,10 +1283,13 @@ public final class NativeArray extends ScriptObject {
// Get only non-missing elements. Missing elements go at the end
// of the sorted array. So, just don't copy these to sort input.
final ArrayList<Object> src = new ArrayList<>();
- for (long i = 0; i < len; i = array.nextIndex(i)) {
- if (array.has((int) i)) {
- src.add(array.getObject((int) i));
+
+ for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
+ final long index = iter.next();
+ if (index >= len) {
+ break;
}
+ src.add(array.getObject((int)index));
}
final Object[] sorted = sort(src.toArray(), comparefn);
@@ -1001,7 +1304,7 @@ public final class NativeArray extends ScriptObject {
}
sobj.setArray(array);
- }
+ }
return sobj;
} catch (final ClassCastException | NullPointerException e) {
@@ -1024,8 +1327,8 @@ public final class NativeArray extends ScriptObject {
return ScriptRuntime.UNDEFINED;
}
- final Object start = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
- final Object deleteCount = (args.length > 1) ? args[1] : ScriptRuntime.UNDEFINED;
+ final Object start = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+ final Object deleteCount = args.length > 1 ? args[1] : ScriptRuntime.UNDEFINED;
Object[] items;
@@ -1054,7 +1357,7 @@ public final class NativeArray extends ScriptObject {
for (int i = 0; i < items.length; i++, k++) {
sobj.defineOwnProperty(k, items[i]);
}
- } catch (UnsupportedOperationException uoe) {
+ } catch (final UnsupportedOperationException uoe) {
returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len);
}
} else {
@@ -1077,18 +1380,18 @@ public final class NativeArray extends ScriptObject {
}
if (items.length < deleteCount) {
- for (long k = start; k < (len - deleteCount); k++) {
+ for (long k = start; k < len - deleteCount; k++) {
final long from = k + deleteCount;
final long to = k + items.length;
if (sobj.has(from)) {
- sobj.set(to, sobj.get(from), true);
+ sobj.set(to, sobj.get(from), CALLSITE_STRICT);
} else {
sobj.delete(to, true);
}
}
- for (long k = len; k > (len - deleteCount + items.length); k--) {
+ for (long k = len; k > len - deleteCount + items.length; k--) {
sobj.delete(k - 1, true);
}
} else if (items.length > deleteCount) {
@@ -1098,7 +1401,7 @@ public final class NativeArray extends ScriptObject {
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, true);
+ sobj.set(to, fromValue, CALLSITE_STRICT);
} else {
sobj.delete(to, true);
}
@@ -1107,11 +1410,11 @@ public final class NativeArray extends ScriptObject {
long k = start;
for (int i = 0; i < items.length; i++, k++) {
- sobj.set(k, items[i], true);
+ sobj.set(k, items[i], CALLSITE_STRICT);
}
final long newLength = len - deleteCount + items.length;
- sobj.set("length", newLength, true);
+ sobj.set("length", newLength, CALLSITE_STRICT);
return array;
}
@@ -1151,19 +1454,19 @@ public final class NativeArray extends ScriptObject {
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, true);
+ sobj.set(to, fromValue, CALLSITE_STRICT);
} else {
sobj.delete(to, true);
}
}
for (int j = 0; j < items.length; j++) {
- sobj.set(j, items[j], true);
+ sobj.set(j, items[j], CALLSITE_STRICT);
}
}
final long newLength = len + items.length;
- sobj.set("length", newLength, true);
+ sobj.set("length", newLength, CALLSITE_STRICT);
return newLength;
}
@@ -1191,7 +1494,7 @@ public final class NativeArray extends ScriptObject {
}
- for (long k = Math.max(0, (n < 0) ? (len - Math.abs(n)) : n); k < len; k++) {
+ for (long k = Math.max(0, n < 0 ? len - Math.abs(n) : n); k < len; k++) {
if (sobj.has(k)) {
if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
return k;
@@ -1222,10 +1525,10 @@ public final class NativeArray extends ScriptObject {
return -1;
}
- final Object searchElement = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
- final long n = (args.length > 1) ? JSType.toLong(args[1]) : (len - 1);
+ final Object searchElement = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+ final long n = args.length > 1 ? JSType.toLong(args[1]) : len - 1;
- for (long k = (n < 0) ? (len - Math.abs(n)) : Math.min(n, len - 1); k >= 0; k--) {
+ for (long k = n < 0 ? len - Math.abs(n) : Math.min(n, len - 1); k >= 0; k--) {
if (sobj.has(k)) {
if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
return k;
@@ -1258,7 +1561,7 @@ public final class NativeArray extends ScriptObject {
@Override
protected boolean forEach(final Object val, final long i) throws Throwable {
- return (result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self));
+ return result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self);
}
}.apply();
}
@@ -1435,4 +1738,166 @@ public final class NativeArray extends ScriptObject {
return false;
}
+
+ @Override
+ public String toString() {
+ return "NativeArray@" + Debug.id(this) + " [" + getArray().getClass().getSimpleName() + ']';
+ }
+
+ @Override
+ public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) {
+ if (clazz == PushLinkLogic.class) {
+ return PushLinkLogic.INSTANCE;
+ } else if (clazz == PopLinkLogic.class) {
+ return PopLinkLogic.INSTANCE;
+ } else if (clazz == ConcatLinkLogic.class) {
+ return ConcatLinkLogic.INSTANCE;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasPerInstanceAssumptions() {
+ return true; //length writable switchpoint
+ }
+
+ /**
+ * This is an abstract super class that contains common functionality for all
+ * specialized optimistic builtins in NativeArray. For example, it handles the
+ * modification switchpoint which is touched when length is written.
+ */
+ private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic {
+ protected ArrayLinkLogic() {
+ }
+
+ protected static ContinuousArrayData getContinuousArrayData(final Object self) {
+ try {
+ //cast to NativeArray, to avoid cases like x = {0:0, 1:1}, x.length = 2, where we can't use the array push/pop
+ return (ContinuousArrayData)((NativeArray)self).getArray();
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Push and pop callsites can throw ClassCastException as a mechanism to have them
+ * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x)
+ * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink
+ */
+ @Override
+ public Class<? extends Throwable> getRelinkException() {
+ return ClassCastException.class;
+ }
+ }
+
+ /**
+ * This is linker logic for optimistic concatenations
+ */
+ private static final class ConcatLinkLogic extends ArrayLinkLogic {
+ private static final LinkLogic INSTANCE = new ConcatLinkLogic();
+
+ @Override
+ public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ final Object[] args = request.getArguments();
+
+ if (args.length != 3) { //single argument check
+ return false;
+ }
+
+ final ContinuousArrayData selfData = getContinuousArrayData(self);
+ if (selfData == null) {
+ return false;
+ }
+
+ final Object arg = args[2];
+ //args[2] continuousarray or non arraydata, let past non array datas
+ if (arg instanceof NativeArray) {
+ final ContinuousArrayData argData = getContinuousArrayData(arg);
+ if (argData == null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * This is linker logic for optimistic pushes
+ */
+ private static final class PushLinkLogic extends ArrayLinkLogic {
+ private static final LinkLogic INSTANCE = new PushLinkLogic();
+
+ @Override
+ public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ return getContinuousArrayData(self) != null;
+ }
+ }
+
+ /**
+ * This is linker logic for optimistic pops
+ */
+ private static final class PopLinkLogic extends ArrayLinkLogic {
+ private static final LinkLogic INSTANCE = new PopLinkLogic();
+
+ /**
+ * We need to check if we are dealing with a continuous non empty array data here,
+ * as pop with a primitive return value returns undefined for arrays with length 0
+ */
+ @Override
+ public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ final ContinuousArrayData data = getContinuousNonEmptyArrayData(self);
+ if (data != null) {
+ final Class<?> elementType = data.getElementType();
+ final Class<?> returnType = desc.getMethodType().returnType();
+ final boolean typeFits = JSType.getAccessorTypeIndex(returnType) >= JSType.getAccessorTypeIndex(elementType);
+ return typeFits;
+ }
+ return false;
+ }
+
+ private static ContinuousArrayData getContinuousNonEmptyArrayData(final Object self) {
+ final ContinuousArrayData data = getContinuousArrayData(self);
+ if (data != null) {
+ return data.length() == 0 ? null : data;
+ }
+ return null;
+ }
+ }
+
+ //runtime calls for push and pops. they could be used as guards, but they also perform the runtime logic,
+ //so rather than synthesizing them into a guard method handle that would also perform the push on the
+ //retrieved receiver, we use this as runtime logic
+
+ //TODO - fold these into the Link logics, but I'll do that as a later step, as I want to do a checkin
+ //where everything works first
+
+ private static final <T> ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class<T> clazz) {
+ try {
+ @SuppressWarnings("unchecked")
+ final ContinuousArrayData data = (ContinuousArrayData)(T)((NativeArray)self).getArray();
+ if (data.length() != 0L) {
+ return data; //if length is 0 we cannot pop and have to relink, because then we'd have to return an undefined, which is a wider type than e.g. int
+ }
+ } catch (final NullPointerException e) {
+ //fallthru
+ }
+ throw new ClassCastException();
+ }
+
+ private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self) {
+ try {
+ return (ContinuousArrayData)((NativeArray)self).getArray();
+ } catch (final NullPointerException e) {
+ throw new ClassCastException();
+ }
+ }
+
+ private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) {
+ try {
+ return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType"
+ } catch (final NullPointerException e) {
+ throw new ClassCastException();
+ }
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index 70c97daf..e3c5c00d 100644
--- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -25,27 +25,81 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+/**
+ * NativeArrayBuffer - ArrayBuffer as described in the JS typed
+ * array spec
+ */
@ScriptClass("ArrayBuffer")
-final class NativeArrayBuffer extends ScriptObject {
- private final byte[] buffer;
+public final class NativeArrayBuffer extends ScriptObject {
+ private final ByteBuffer nb;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
+ /**
+ * Constructor
+ * @param nb native byte buffer to wrap
+ * @param global global instance
+ */
+ protected NativeArrayBuffer(final ByteBuffer nb, final Global global) {
+ super(global.getArrayBufferPrototype(), $nasgenmap$);
+ this.nb = nb;
+ }
+
+ /**
+ * Constructor
+ * @param nb native byte buffer to wrap
+ */
+ protected NativeArrayBuffer(final ByteBuffer nb) {
+ this(nb, Global.instance());
+ }
+
+ /**
+ * Constructor
+ * @param byteLength byteLength for buffer
+ */
+ protected NativeArrayBuffer(final int byteLength) {
+ this(ByteBuffer.allocateDirect(byteLength));
+ }
+
+ /**
+ * Clone constructor
+ * Used only for slice
+ * @param other original buffer
+ * @param begin begin byte index
+ * @param end end byte index
+ */
+ protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
+ this(cloneBuffer(other.getNioBuffer(), begin, end));
+ }
+
+ /**
+ * Constructor
+ * @param newObj is this invoked with new
+ * @param self self reference
+ * @param args arguments to constructor
+ * @return new NativeArrayBuffer
+ */
@Constructor(arity = 1)
public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
+ if (!newObj) {
+ throw typeError("constructor.requires.new", "ArrayBuffer");
+ }
+
if (args.length == 0) {
throw new RuntimeException("missing length argument");
}
@@ -53,21 +107,19 @@ final class NativeArrayBuffer extends ScriptObject {
return new NativeArrayBuffer(JSType.toInt32(args[0]));
}
- protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
- super(global.getArrayBufferPrototype(), $nasgenmap$);
- this.buffer = byteArray;
- }
-
- protected NativeArrayBuffer(final byte[] byteArray) {
- this(byteArray, Global.instance());
+ private static ByteBuffer cloneBuffer(final ByteBuffer original, final int begin, final int end) {
+ final ByteBuffer clone = ByteBuffer.allocateDirect(original.capacity());
+ original.rewind();//copy from the beginning
+ clone.put(original);
+ original.rewind();
+ clone.flip();
+ clone.position(begin);
+ clone.limit(end);
+ return clone.slice();
}
- protected NativeArrayBuffer(final int byteLength) {
- this(new byte[byteLength]);
- }
-
- protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
- this(Arrays.copyOfRange(other.buffer, begin, end));
+ ByteBuffer getNioBuffer() {
+ return nb;
}
@Override
@@ -75,19 +127,68 @@ final class NativeArrayBuffer extends ScriptObject {
return "ArrayBuffer";
}
+ /**
+ * Byte length for native array buffer
+ * @param self native array buffer
+ * @return byte length
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteLength(final Object self) {
- return ((NativeArrayBuffer)self).buffer.length;
+ public static int byteLength(final Object self) {
+ return ((NativeArrayBuffer)self).getByteLength();
+ }
+
+ /**
+ * Returns true if an object is an ArrayBufferView
+ *
+ * @param self self
+ * @param obj object to check
+ *
+ * @return true if obj is an ArrayBufferView
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isView(final Object self, final Object obj) {
+ return obj instanceof ArrayBufferView;
}
+ /**
+ * Slice function
+ * @param self native array buffer
+ * @param begin0 start byte index
+ * @param end0 end byte index
+ * @return new array buffer, sliced
+ */
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
- int begin = JSType.toInt32(begin0);
- int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
- begin = adjustIndex(begin, arrayBuffer.getByteLength());
- end = adjustIndex(end, arrayBuffer.getByteLength());
- return new NativeArrayBuffer((NativeArrayBuffer) self, begin, Math.max(end, begin));
+ final int byteLength = arrayBuffer.getByteLength();
+ final int begin = adjustIndex(JSType.toInt32(begin0), byteLength);
+ final int end = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength, byteLength);
+ return new NativeArrayBuffer(arrayBuffer, begin, Math.max(end, begin));
+ }
+
+ /**
+ * Specialized slice function
+ * @param self native array buffer
+ * @param begin start byte index
+ * @param end end byte index
+ * @return new array buffer, sliced
+ */
+ @SpecializedFunction
+ public static Object slice(final Object self, final int begin, final int end) {
+ final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
+ final int byteLength = arrayBuffer.getByteLength();
+ return new NativeArrayBuffer(arrayBuffer, adjustIndex(begin, byteLength), Math.max(adjustIndex(end, byteLength), begin));
+ }
+
+ /**
+ * Specialized slice function
+ * @param self native array buffer
+ * @param begin start byte index
+ * @return new array buffer, sliced
+ */
+ @SpecializedFunction
+ public static Object slice(final Object self, final int begin) {
+ return slice(self, begin, ((NativeArrayBuffer)self).getByteLength());
}
/**
@@ -100,10 +201,7 @@ final class NativeArrayBuffer extends ScriptObject {
* @return valid index index in the range [0, length).
*/
static int adjustIndex(final int index, final int length) {
- if (index < 0) {
- return clamp(index + length, length);
- }
- return clamp(index, length);
+ return index < 0 ? clamp(index + length, length) : clamp(index, length);
}
/**
@@ -118,23 +216,19 @@ final class NativeArrayBuffer extends ScriptObject {
return index;
}
- public byte[] getByteArray() {
- return buffer;
- }
-
- public int getByteLength() {
- return buffer.length;
+ int getByteLength() {
+ return nb.limit();
}
ByteBuffer getBuffer() {
- return ByteBuffer.wrap(buffer);
+ return nb;
}
ByteBuffer getBuffer(final int offset) {
- return ByteBuffer.wrap(buffer, offset, buffer.length - offset);
+ return (ByteBuffer)nb.duplicate().position(offset);
}
ByteBuffer getBuffer(final int offset, final int length) {
- return ByteBuffer.wrap(buffer, offset, length);
+ return (ByteBuffer)getBuffer(offset).limit(length);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeBoolean.java b/src/jdk/nashorn/internal/objects/NativeBoolean.java
index d645d6dd..7bce42bd 100644
--- a/src/jdk/nashorn/internal/objects/NativeBoolean.java
+++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java
@@ -25,8 +25,8 @@
package jdk.nashorn.internal.objects;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -51,9 +51,9 @@ import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
public final class NativeBoolean extends ScriptObject {
private final boolean value;
- // Method handle to create an object wrapper for a primitive boolean
- private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
- // Method handle to retrieve the Boolean prototype object
+ /** Method handle to create an object wrapper for a primitive boolean. */
+ static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
+ /** Method handle to retrieve the Boolean prototype object. */
private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
diff --git a/src/jdk/nashorn/internal/objects/NativeDataView.java b/src/jdk/nashorn/internal/objects/NativeDataView.java
index 414ff8ae..14c11f69 100644
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -24,9 +24,9 @@
*/
package jdk.nashorn.internal.objects;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -35,7 +35,6 @@ import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -88,15 +87,15 @@ public class NativeDataView extends ScriptObject {
// underlying ByteBuffer
private final ByteBuffer buf;
- private NativeDataView(NativeArrayBuffer arrBuf) {
+ private NativeDataView(final NativeArrayBuffer arrBuf) {
this(arrBuf, arrBuf.getBuffer(), 0);
}
- private NativeDataView(NativeArrayBuffer arrBuf, int offset) {
+ private NativeDataView(final NativeArrayBuffer arrBuf, final int offset) {
this(arrBuf, bufferFrom(arrBuf, offset), offset);
}
- private NativeDataView(NativeArrayBuffer arrBuf, int offset, int length) {
+ private NativeDataView(final NativeArrayBuffer arrBuf, final int offset, final int length) {
this(arrBuf, bufferFrom(arrBuf, offset, length), offset, length);
}
@@ -106,10 +105,10 @@ public class NativeDataView extends ScriptObject {
private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) {
super(Global.instance().getDataViewPrototype(), $nasgenmap$);
- this.buffer = arrBuf;
+ this.buffer = arrBuf;
this.byteOffset = offset;
this.byteLength = length;
- this.buf = buf;
+ this.buf = buf;
}
/**
@@ -136,14 +135,14 @@ public class NativeDataView extends ScriptObject {
throw typeError("not.an.arraybuffer.in.dataview");
}
- final NativeArrayBuffer arrBuf = (NativeArrayBuffer) args[0];
+ final NativeArrayBuffer arrBuf = (NativeArrayBuffer)args[0];
switch (args.length) {
- case 1:
- return new NativeDataView(arrBuf);
- case 2:
- return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
- default:
- return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
+ case 1:
+ return new NativeDataView(arrBuf);
+ case 2:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
+ default:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
}
}
@@ -156,7 +155,7 @@ public class NativeDataView extends ScriptObject {
* @param offset offset in bytes from the start of the ArrayBuffer
* @return newly constructed DataView object
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) {
if (!(arrBuf instanceof NativeArrayBuffer)) {
throw typeError("not.an.arraybuffer.in.dataview");
@@ -174,7 +173,7 @@ public class NativeDataView extends ScriptObject {
* @param length is the number of bytes from the offset that this DataView will reference
* @return newly constructed DataView object
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) {
if (!(arrBuf instanceof NativeArrayBuffer)) {
throw typeError("not.an.arraybuffer.in.dataview");
@@ -204,8 +203,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt8(final Object self, final Object byteOffset) {
try {
return getBuffer(self).get(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -220,8 +219,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt8(final Object self, final int byteOffset) {
try {
return getBuffer(self).get(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -235,9 +234,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static int getUint8(final Object self, final Object byteOffset) {
try {
- return (0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFF & getBuffer(self).get(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -251,9 +250,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint8(final Object self, final int byteOffset) {
try {
- return (0xFF & getBuffer(self).get(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFF & getBuffer(self).get(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -269,8 +268,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -285,8 +284,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getShort(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -302,8 +301,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getShort(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -318,9 +317,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) {
try {
- return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -334,9 +333,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint16(final Object self, final int byteOffset) {
try {
- return (int) (0xFFFF & getBuffer(self, false).getShort(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, false).getShort(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -351,9 +350,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) {
try {
- return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -369,8 +368,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -385,8 +384,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getInt(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -402,8 +401,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getInt(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -418,9 +417,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -434,9 +433,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static long getUint32(final Object self, final int byteOffset) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return JSType.toUint32(getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -451,9 +450,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return JSType.toUint32(getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -469,8 +468,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -485,8 +484,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getFloat(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -502,8 +501,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getFloat(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -519,8 +518,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -535,8 +534,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getDouble(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -552,8 +551,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getDouble(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -582,8 +581,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -600,8 +599,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(byteOffset, (byte)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -618,8 +617,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -636,8 +635,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(byteOffset, (byte)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -655,8 +654,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -673,8 +672,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -692,8 +691,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -711,8 +710,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -729,8 +728,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -748,8 +747,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -765,10 +764,10 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
try {
- getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toInt32(value));
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -785,8 +784,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putInt(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -804,8 +803,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -823,8 +822,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -841,8 +840,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putInt(byteOffset, (int)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -860,8 +859,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(byteOffset, (int)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -879,8 +878,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -897,8 +896,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putFloat(byteOffset, (float)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -916,8 +915,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putFloat(byteOffset, (float)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -935,8 +934,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -953,8 +952,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putDouble(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -972,8 +971,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putDouble(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -981,22 +980,22 @@ public class NativeDataView extends ScriptObject {
private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) {
try {
return nab.getBuffer(offset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.constructor.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.constructor.offset");
}
}
private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) {
try {
return nab.getBuffer(offset, length);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.constructor.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.constructor.offset");
}
}
private static NativeDataView checkSelf(final Object self) {
if (!(self instanceof NativeDataView)) {
- throw typeError("not.an.arraybuffer", ScriptRuntime.safeToString(self));
+ throw typeError("not.an.arraybuffer.in.dataview", ScriptRuntime.safeToString(self));
}
return (NativeDataView)self;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeDate.java b/src/jdk/nashorn/internal/objects/NativeDate.java
index b3661df7..bb499c26 100644
--- a/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -30,7 +30,6 @@ import static java.lang.Double.isInfinite;
import static java.lang.Double.isNaN;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.Callable;
@@ -38,7 +37,7 @@ import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.parser.DateParser;
import jdk.nashorn.internal.runtime.ConsString;
@@ -155,7 +154,7 @@ public final class NativeDate extends ScriptObject {
* @param self self references
* @return Date representing now
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static Object construct(final boolean isNew, final Object self) {
final NativeDate result = new NativeDate();
return isNew ? result : toStringImpl(result, FORMAT_DATE_TIME);
@@ -909,6 +908,7 @@ public final class NativeDate extends ScriptObject {
sb.append(n);
}
+ @SuppressWarnings("fallthrough")
private static String toStringImpl(final Object self, final int format) {
final NativeDate nd = getNativeDate(self);
@@ -934,7 +934,6 @@ public final class NativeDate extends ScriptObject {
}
sb.append(' ');
- //$FALL-THROUGH$
case FORMAT_TIME:
final TimeZone tz = nd.getTimeZone();
final double utcTime = nd.getTime();
@@ -1046,7 +1045,8 @@ public final class NativeDate extends ScriptObject {
// ECMA 15.9.1.2 TimeWithinDay (t)
private static double timeWithinDay(final double t) {
- return t % msPerDay;
+ final double val = t % msPerDay;
+ return val < 0? val + msPerDay : val;
}
// ECMA 15.9.1.3 InLeapYear (t)
diff --git a/src/jdk/nashorn/internal/objects/NativeDebug.java b/src/jdk/nashorn/internal/objects/NativeDebug.java
index 5d80c37b..c42e7843 100644
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -26,19 +26,23 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
import java.io.PrintWriter;
+import java.util.LinkedList;
import java.util.Objects;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyListeners;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
* Nashorn specific debug utils. This is meant for Nashorn developers.
@@ -63,6 +67,36 @@ public final class NativeDebug extends ScriptObject {
}
/**
+ * Return the ArrayData class for this ScriptObject
+ * @param self self
+ * @param obj script object to check
+ * @return ArrayData class, or undefined if no ArrayData is present
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getArrayDataClass(final Object self, final Object obj) {
+ try {
+ return ((ScriptObject)obj).getArray().getClass();
+ } catch (final ClassCastException e) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ }
+
+ /**
+ * Return the ArrayData for this ScriptObject
+ * @param self self
+ * @param obj script object to check
+ * @return ArrayData, ArrayDatas have toString methods, return Undefined if data missing
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getArrayData(final Object self, final Object obj) {
+ try {
+ return ((ScriptObject)obj).getArray();
+ } catch (final ClassCastException e) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ }
+
+ /**
* Nashorn extension: get context, context utility
*
* @param self self reference
@@ -93,21 +127,6 @@ public final class NativeDebug extends ScriptObject {
}
/**
- * Nashorn extension: get spill vector from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the spill vector for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object spill(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).spill;
- }
- return UNDEFINED;
- }
-
- /**
* Check object identity comparison regardless of type
*
* @param self self reference
@@ -121,6 +140,31 @@ public final class NativeDebug extends ScriptObject {
}
/**
+ * Returns true if if the two objects are both property maps, and they have identical properties in the same order,
+ * but allows the properties to differ in their types.
+ * @param self self
+ * @param m1 first property map
+ * @param m2 second property map
+ * @return true if they have identical properties in same order, with possibly different types.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object equalWithoutType(final Object self, final Object m1, final Object m2) {
+ return ((PropertyMap)m1).equalsWithoutType((PropertyMap)m2);
+ }
+
+ /**
+ * Returns a diagnostic string representing the difference of two property maps.
+ * @param self self
+ * @param m1 first property map
+ * @param m2 second property map
+ * @return a diagnostic string representing the difference of two property maps.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object diffPropertyMaps(final Object self, final Object m1, final Object m2) {
+ return PropertyMap.diff((PropertyMap)m1, (PropertyMap)m2);
+ }
+
+ /**
* Object util - getClass
*
* @param self self reference
@@ -196,7 +240,6 @@ public final class NativeDebug extends ScriptObject {
* @param self self reference
* @return undefined
*/
- @SuppressWarnings("resource")
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object dumpCounters(final Object self) {
final PrintWriter out = Context.getCurrentErr();
@@ -210,7 +253,6 @@ public final class NativeDebug extends ScriptObject {
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
out.println("PropertyMap count " + PropertyMap.getCount());
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
- out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
@@ -223,4 +265,133 @@ public final class NativeDebug extends ScriptObject {
return UNDEFINED;
}
+
+ /*
+ * Framework for logging runtime events
+ */
+
+ private static final String EVENT_QUEUE = "__eventQueue__";
+ private static final String EVENT_QUEUE_CAPACITY = "__eventQueueCapacity__";
+
+ /**
+ * Get the capacity of the event queue
+ * @param self self reference
+ * @return capacity of event queue as an integer
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getEventQueueCapacity(final Object self) {
+ final ScriptObject sobj = (ScriptObject)self;
+ Integer cap;
+ if (sobj.has(EVENT_QUEUE_CAPACITY)) {
+ cap = JSType.toInt32(sobj.get(EVENT_QUEUE_CAPACITY));
+ } else {
+ setEventQueueCapacity(self, cap = RuntimeEvent.RUNTIME_EVENT_QUEUE_SIZE);
+ }
+ return cap;
+ }
+
+ /**
+ * Set the event queue capacity
+ * @param self an event queue
+ * @param newCapacity new capacity
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
+ ((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, NashornCallSiteDescriptor.CALLSITE_STRICT);
+ }
+
+ /**
+ * Add a runtime event to the runtime event queue. The queue has a fixed
+ * size {@link RuntimeEvent#RUNTIME_EVENT_QUEUE_SIZE} and the oldest
+ * entry will be thrown out of the queue is about to overflow
+ * @param self self reference
+ * @param event event to add
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void addRuntimeEvent(final Object self, final Object event) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final int cap = (Integer)getEventQueueCapacity(self);
+ while (q.size() >= cap) {
+ q.removeFirst();
+ }
+ q.addLast(getEvent(event));
+ }
+
+ /**
+ * Expands the event queue capacity, or truncates if capacity is lower than
+ * current capacity. Then only the newest entries are kept
+ * @param self self reference
+ * @param newCapacity new capacity
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void expandEventQueueCapacity(final Object self, final Object newCapacity) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final int nc = JSType.toInt32(newCapacity);
+ while (q.size() > nc) {
+ q.removeFirst();
+ }
+ setEventQueueCapacity(self, nc);
+ }
+
+ /**
+ * Clear the runtime event queue
+ * @param self self reference
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void clearRuntimeEvents(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ q.clear();
+ }
+
+ /**
+ * Remove a specific runtime event from the event queue
+ * @param self self reference
+ * @param event event to remove
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void removeRuntimeEvent(final Object self, final Object event) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final RuntimeEvent<?> re = getEvent(event);
+ if (!q.remove(re)) {
+ throw new IllegalStateException("runtime event " + re + " was not in event queue");
+ }
+ }
+
+ /**
+ * Return all runtime events in the queue as an array
+ * @param self self reference
+ * @return array of events
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getRuntimeEvents(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ return q.toArray(new RuntimeEvent<?>[q.size()]);
+ }
+
+ /**
+ * Return the last runtime event in the queue
+ * @param self self reference
+ * @return the freshest event, null if queue is empty
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getLastRuntimeEvent(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ return q.isEmpty() ? null : q.getLast();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static LinkedList<RuntimeEvent<?>> getEventQueue(final Object self) {
+ final ScriptObject sobj = (ScriptObject)self;
+ LinkedList<RuntimeEvent<?>> q;
+ if (sobj.has(EVENT_QUEUE)) {
+ q = (LinkedList<RuntimeEvent<?>>)((ScriptObject)self).get(EVENT_QUEUE);
+ } else {
+ ((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), NashornCallSiteDescriptor.CALLSITE_STRICT);
+ }
+ return q;
+ }
+
+ private static RuntimeEvent<?> getEvent(final Object event) {
+ return (RuntimeEvent<?>)event;
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeError.java b/src/jdk/nashorn/internal/objects/NativeError.java
index 18aa11e5..e1d95ce0 100644
--- a/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeError.java
@@ -25,12 +25,11 @@
package jdk.nashorn.internal.objects;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -41,8 +40,8 @@ import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
@@ -147,8 +146,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object captureStackTrace(final Object self, final Object errorObj) {
- Global.checkObject(errorObj);
- final ScriptObject sobj = (ScriptObject)errorObj;
+ final ScriptObject sobj = Global.checkObject(errorObj);
initException(sobj);
sobj.delete(STACK, false);
if (! sobj.has("stack")) {
@@ -184,8 +182,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object printStackTrace(final Object self) {
- Global.checkObject(self);
- return ECMAException.printStackTrace((ScriptObject)self);
+ return ECMAException.printStackTrace(Global.checkObject(self));
}
/**
@@ -199,8 +196,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object getStackTrace(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
final Object exception = ECMAException.getException(sobj);
Object[] res;
if (exception instanceof Throwable) {
@@ -220,8 +216,7 @@ public final class NativeError extends ScriptObject {
* @return line number from which error was thrown
*/
public static Object getLineNumber(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(LINENUMBER) ? sobj.get(LINENUMBER) : ECMAException.getLineNumber(sobj);
}
@@ -234,8 +229,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setLineNumber(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(LINENUMBER)) {
sobj.put(LINENUMBER, value, false);
} else {
@@ -252,8 +246,7 @@ public final class NativeError extends ScriptObject {
* @return column number from which error was thrown
*/
public static Object getColumnNumber(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(COLUMNNUMBER) ? sobj.get(COLUMNNUMBER) : ECMAException.getColumnNumber((ScriptObject)self);
}
@@ -266,8 +259,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setColumnNumber(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(COLUMNNUMBER)) {
sobj.put(COLUMNNUMBER, value, false);
} else {
@@ -284,8 +276,7 @@ public final class NativeError extends ScriptObject {
* @return file name from which error was thrown
*/
public static Object getFileName(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(FILENAME) ? sobj.get(FILENAME) : ECMAException.getFileName((ScriptObject)self);
}
@@ -298,8 +289,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setFileName(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(FILENAME)) {
sobj.put(FILENAME, value, false);
} else {
@@ -318,15 +308,14 @@ public final class NativeError extends ScriptObject {
* @return value of "stack" property
*/
public static Object getStack(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.has(STACK)) {
return sobj.get(STACK);
}
final Object exception = ECMAException.getException(sobj);
if (exception instanceof Throwable) {
- Object value = getScriptStackString(sobj, (Throwable)exception);
+ final Object value = getScriptStackString(sobj, (Throwable)exception);
if (sobj.hasOwnProperty(STACK)) {
sobj.put(STACK, value, false);
} else {
@@ -349,14 +338,12 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setStack(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(STACK)) {
sobj.put(STACK, value, false);
} else {
sobj.addOwnProperty(STACK, Attribute.NOT_ENUMERABLE, value);
}
-
return value;
}
@@ -370,9 +357,7 @@ public final class NativeError extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object toString(final Object self) {
// Step 1 and 2 : check if 'self' is object it not throw TypeError
- Global.checkObject(self);
-
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
// Step 3 & 4 : get "name" and convert to String.
// But if message is undefined make it "Error".
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index a9dfb7a4..ef7a1ff8 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -25,6 +25,12 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Float32 array for the TypedArray extension
@@ -56,73 +63,118 @@ public final class NativeFloat32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeFloat32Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Float32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Float32ArrayData(nb.asFloatBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Float32ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Float32Array";
}
};
- private static final class Float32ArrayData extends ArrayDataImpl {
- private Float32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Float32ArrayData extends TypedArrayData<FloatBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "getElem", double.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+ private Float32ArrayData(final FloatBuffer nb, final int start, final int end) {
+ super(((FloatBuffer)nb.position(start).limit(end)).slice(), end - start);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public Class<?> getElementType() {
+ return double.class;
}
@Override
- protected double getDoubleImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- final int bits = byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
- return Float.intBitsToFloat(bits);
+ public Class<?> getBoxedElementType() {
+ return Double.class;
}
@Override
- protected int getIntImpl(final int index) {
- return (int)getDoubleImpl(index);
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected long getLongImpl(final int key) {
- return (long)getDoubleImpl(key);
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private double getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final double elem) {
+ try {
+ nb.put(index, (float)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected Object getObjectImpl(final int key) {
- return getDoubleImpl(key);
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class || returnType == long.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
}
@Override
- protected void setImpl(final int index, final double value) {
- final int bits = Float.floatToRawIntBits((float)value);
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(bits & 0xff);
- byteArray[byteIndex+1] = (byte)(bits >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
+ public int getInt(final int index) {
+ return (int)getDouble(index);
}
@Override
- protected void setImpl(final int key, final int value) {
- setImpl(key, (double)value);
+ public long getLong(final int index) {
+ return (long)getDouble(index);
}
@Override
- protected void setImpl(final int key, final long value) {
- setImpl(key, (double)value);
+ public double getDouble(final int index) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getDouble(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ return set(index, (double)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (double)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
}
@@ -137,7 +189,7 @@ public final class NativeFloat32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeFloat32Array)constructorImpl(args, FACTORY);
+ return (NativeFloat32Array)constructorImpl(newObj, args, FACTORY);
}
NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -145,11 +197,6 @@ public final class NativeFloat32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Float32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index 61b58807..d0413d08 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -25,6 +25,12 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.DoubleBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Float64 array for the TypedArray extension
@@ -56,83 +63,118 @@ public final class NativeFloat64Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeFloat64Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Float64ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+ return new Float64ArrayData(nb.asDoubleBuffer(), start, length);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Float64ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Float64Array";
}
};
- private static final class Float64ArrayData extends ArrayDataImpl {
- private Float64ArrayData(final NativeArrayBuffer buffer,
- final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Float64ArrayData extends TypedArrayData<DoubleBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "getElem", double.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+ private Float64ArrayData(final DoubleBuffer nb, final int start, final int end) {
+ super(((DoubleBuffer)nb.position(start).limit(end)).slice(), end - start);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected double getDoubleImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- final long bits;
- bits = byteArray[byteIndex ] & 0x0000_0000_0000_00ffL |
- (long)byteArray[byteIndex+1] << 8 & 0x0000_0000_0000_ff00L |
- (long)byteArray[byteIndex+2] << 16 & 0x0000_0000_00ff_0000L |
- (long)byteArray[byteIndex+3] << 24 & 0x0000_0000_ff00_0000L |
- (long)byteArray[byteIndex+4] << 32 & 0x0000_00ff_0000_0000L |
- (long)byteArray[byteIndex+5] << 40 & 0x0000_ff00_0000_0000L |
- (long)byteArray[byteIndex+6] << 48 & 0x00ff_0000_0000_0000L |
- (long)byteArray[byteIndex+7] << 56 & 0xff00_0000_0000_0000L ;
- return Double.longBitsToDouble(bits);
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
}
@Override
- protected int getIntImpl(final int index) {
- return (int)getDoubleImpl(index);
+ public Class<?> getElementType() {
+ return double.class;
}
@Override
- protected long getLongImpl(final int key) {
- return (long)getDoubleImpl(key);
+ public Class<?> getBoxedElementType() {
+ return Double.class;
+ }
+
+ private double getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final double elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected Object getObjectImpl(final int key) {
- return getDoubleImpl(key);
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class || returnType == long.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
}
@Override
- protected void setImpl(final int index, final double value) {
- final long bits = Double.doubleToRawLongBits(value);
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(bits & 0xff);
- byteArray[byteIndex+1] = (byte)(bits >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
- byteArray[byteIndex+4] = (byte)(bits >>> 32 & 0xff);
- byteArray[byteIndex+5] = (byte)(bits >>> 40 & 0xff);
- byteArray[byteIndex+6] = (byte)(bits >>> 48 & 0xff);
- byteArray[byteIndex+7] = (byte)(bits >>> 56 & 0xff);
+ public int getInt(final int index) {
+ return (int)getDouble(index);
}
@Override
- protected void setImpl(final int key, final int value) {
- setImpl(key, (double)value);
+ public long getLong(final int index) {
+ return (long)getDouble(index);
}
@Override
- protected void setImpl(final int key, final long value) {
- setImpl(key, (double)value);
+ public double getDouble(final int index) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getDouble(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ return set(index, (double)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (double)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
}
@@ -147,7 +189,7 @@ public final class NativeFloat64Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeFloat64Array)constructorImpl(args, FACTORY);
+ return (NativeFloat64Array)constructorImpl(newObj, args, FACTORY);
}
NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -155,11 +197,6 @@ public final class NativeFloat64Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Float64Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java
index 013683e0..bd2f2dd9 100644
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -25,12 +25,15 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.List;
-
+import jdk.internal.dynalink.support.Lookup;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -41,10 +44,11 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
* ECMA 15.3 Function Objects
@@ -56,6 +60,9 @@ import jdk.nashorn.internal.runtime.Source;
@ScriptClass("Function")
public final class NativeFunction {
+ /** apply arg converter handle */
+ public static final MethodHandle TO_APPLY_ARGS = Lookup.findOwnStatic(MethodHandles.lookup(), "toApplyArgs", Object[].class, Object.class);
+
// initialized by nasgen
@SuppressWarnings("unused")
private static PropertyMap $nasgenmap$;
@@ -89,50 +96,75 @@ public final class NativeFunction {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object apply(final Object self, final Object thiz, final Object array) {
- if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
- }
+ checkCallable(self);
- Object[] args = null;
+ final Object[] args = toApplyArgs(array);
- if (array instanceof ScriptObject) {
+ if (self instanceof ScriptFunction) {
+ return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
+ } else if (self instanceof JSObject) {
+ return ((JSObject)self).call(thiz, args);
+ }
+ throw new AssertionError("Should not reach here");
+ }
+
+ /**
+ * Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply
+ * or for direct invocation of the applied function.
+ * @param array the array-like object. Can be null in which case a zero-length array is created.
+ * @return the Java array
+ */
+ public static Object[] toApplyArgs(final Object array) {
+ if (array instanceof NativeArguments) {
+ return ((NativeArguments)array).getArray().asObjectArray();
+ } else if (array instanceof ScriptObject) {
// look for array-like object
final ScriptObject sobj = (ScriptObject)array;
- final Object len = sobj.getLength();
- final int n = (int)JSType.toUint32(len);
+ final int n = lengthToInt(sobj.getLength());
- args = new Object[n];
+ final Object[] args = new Object[n];
for (int i = 0; i < args.length; i++) {
args[i] = sobj.get(i);
}
+ return args;
} else if (array instanceof Object[]) {
- args = (Object[])array;
+ return (Object[])array;
} else if (array instanceof List) {
final List<?> list = (List<?>)array;
- list.toArray(args = new Object[list.size()]);
+ return list.toArray(new Object[list.size()]);
} else if (array == null || array == UNDEFINED) {
- args = ScriptRuntime.EMPTY_ARRAY;
+ return ScriptRuntime.EMPTY_ARRAY;
} else if (array instanceof JSObject) {
// look for array-like JSObject object
final JSObject jsObj = (JSObject)array;
- final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
- final int n = (int)JSType.toUint32(len);
+ final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
+ final int n = lengthToInt(len);
- args = new Object[n];
+ final Object[] args = new Object[n];
for (int i = 0; i < args.length; i++) {
args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED;
}
+ return args;
} else {
throw typeError("function.apply.expects.array");
}
+ }
- if (self instanceof ScriptFunction) {
- return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
- } else if (self instanceof JSObject) {
- return ((JSObject)self).call(thiz, args);
+ private static int lengthToInt(final Object len) {
+ final long ln = JSType.toUint32(len);
+ // NOTE: ECMASCript 5.1 section 15.3.4.3 says length should be treated as Uint32, but we wouldn't be able to
+ // allocate a Java array of more than MAX_VALUE elements anyway, so at this point we have to throw an error.
+ // People applying a function to more than 2^31 arguments will unfortunately be out of luck.
+ if (ln > Integer.MAX_VALUE) {
+ throw rangeError("range.error.inappropriate.array.length", JSType.toString(len));
}
+ return (int)ln;
+ }
- throw new AssertionError("should not reach here");
+ private static void checkCallable(final Object self) {
+ if (!(self instanceof ScriptFunction || (self instanceof JSObject && ((JSObject)self).isFunction()))) {
+ throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+ }
}
/**
@@ -144,11 +176,9 @@ public final class NativeFunction {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static Object call(final Object self, final Object... args) {
- if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
- }
+ checkCallable(self);
- Object thiz = (args.length == 0) ? UNDEFINED : args[0];
+ final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
Object[] arguments;
if (args.length > 1) {
@@ -175,11 +205,7 @@ public final class NativeFunction {
* @return function with bound arguments
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static ScriptFunction bind(final Object self, final Object... args) {
- if (!(self instanceof ScriptFunction)) {
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
- }
-
+ public static Object bind(final Object self, final Object... args) {
final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
Object[] arguments;
@@ -190,7 +216,7 @@ public final class NativeFunction {
arguments = ScriptRuntime.EMPTY_ARRAY;
}
- return ((ScriptFunctionImpl)self).makeBoundFunction(thiz, arguments);
+ return Bootstrap.bindCallable(self, thiz, arguments);
}
/**
@@ -236,7 +262,7 @@ public final class NativeFunction {
funcBody = JSType.toString(args[args.length - 1]);
final String paramList = paramListBuf.toString();
- if (! paramList.isEmpty()) {
+ if (!paramList.isEmpty()) {
checkFunctionParameters(paramList);
sb.append(paramList);
}
@@ -258,8 +284,7 @@ public final class NativeFunction {
}
private static void checkFunctionParameters(final String params) {
- final Source src = sourceFor("<function>", params);
- final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+ final Parser parser = getParser(params);
try {
parser.parseFormalParameterList();
} catch (final ParserException pe) {
@@ -268,12 +293,16 @@ public final class NativeFunction {
}
private static void checkFunctionBody(final String funcBody) {
- final Source src = sourceFor("<function>", funcBody);
- final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+ final Parser parser = getParser(funcBody);
try {
parser.parseFunctionBody();
} catch (final ParserException pe) {
pe.throwAsEcmaException();
}
}
+
+ private static Parser getParser(final String sourceText) {
+ final ScriptEnvironment env = Global.getEnv();
+ return new Parser(env, sourceFor("<function>", sourceText), new Context.ThrowErrorManager(), env._strict, null);
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index f6aa2054..e4cdce51 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int16 array for the TypedArray extension
@@ -56,37 +64,120 @@ public final class NativeInt16Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeInt16Array(buffer, byteOffset, length);
}
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int16ArrayData(buffer, byteOffset, length);
+ public Int16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Int16ArrayData(nb.asShortBuffer(), start, end);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Int16Array";
}
};
- private static final class Int16ArrayData extends ArrayDataImpl {
- private Int16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int16ArrayData extends TypedArrayData<ShortBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int16ArrayData(final ShortBuffer nb, final int start, final int end) {
+ super(((ShortBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (short)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & (short)0x00ff |
- byteArray[byteIndex+1] << 8 & (short)0xff00 ;
+ public Object getObject(final int index) {
+ return getInt(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -101,7 +192,7 @@ public final class NativeInt16Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt16Array)constructorImpl(args, FACTORY);
+ return (NativeInt16Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -109,11 +200,6 @@ public final class NativeInt16Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int16Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index 643bd816..9e664ed7 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int32 array for the TypedArray extension
@@ -55,41 +63,119 @@ public final class NativeInt32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeInt32Array(buffer, byteOffset, length);
}
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int32ArrayData(buffer, byteOffset, length);
+ public Int32ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+ return new Int32ArrayData(nb.asIntBuffer(), start, length);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Int32Array";
}
};
- private static final class Int32ArrayData extends ArrayDataImpl {
- private Int32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int32ArrayData extends TypedArrayData<IntBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int32ArrayData(final IntBuffer nb, final int start, final int end) {
+ super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+ public Object getObject(final int index) {
+ return getInt(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -104,7 +190,7 @@ public final class NativeInt32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt32Array)constructorImpl(args, FACTORY);
+ return (NativeInt32Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -112,11 +198,6 @@ public final class NativeInt32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index 5822c6d5..c336d274 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -25,15 +25,22 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int8Array for the TypedArray extension
@@ -57,32 +64,122 @@ public final class NativeInt8Array extends ArrayBufferView {
}
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int8ArrayData(buffer, byteOffset, length);
+ public Int8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Int8ArrayData(nb, start, end);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Int8Array";
}
};
- private static final class Int8ArrayData extends ArrayDataImpl {
- private Int8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int8ArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int8ArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (byte)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public long getLong(final int index) {
+ return getInt(index);
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)];
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- buffer.getByteArray()[byteIndex(index)] = (byte)value;
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
+
/**
* Constructor
*
@@ -94,7 +191,7 @@ public final class NativeInt8Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt8Array)constructorImpl(args, FACTORY);
+ return (NativeInt8Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -102,11 +199,6 @@ public final class NativeInt8Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int8Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index 84036a32..c5ca9101 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -25,9 +25,10 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -38,6 +39,7 @@ import java.util.List;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.FindProperty;
@@ -47,7 +49,6 @@ import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
-import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.scripts.JO;
/**
@@ -168,63 +169,63 @@ public final class NativeJSAdapter extends ScriptObject {
}
@Override
- public int getInt(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public long getLong(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public double getDouble(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
@@ -248,146 +249,146 @@ public final class NativeJSAdapter extends ScriptObject {
}
@Override
- public void set(final Object key, final int value, final boolean strict) {
+ public void set(final Object key, final int value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final Object key, final long value, final boolean strict) {
+ public void set(final Object key, final long value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final Object key, final double value, final boolean strict) {
+ public void set(final Object key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final Object key, final Object value, final boolean strict) {
+ public void set(final Object key, final Object value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final double key, final int value, final boolean strict) {
+ public void set(final double key, final int value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final double key, final long value, final boolean strict) {
+ public void set(final double key, final long value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final double key, final double value, final boolean strict) {
+ public void set(final double key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final double key, final Object value, final boolean strict) {
+ public void set(final double key, final Object value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final long key, final int value, final boolean strict) {
+ public void set(final long key, final int value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final long key, final long value, final boolean strict) {
+ public void set(final long key, final long value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final long key, final double value, final boolean strict) {
+ public void set(final long key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final long key, final Object value, final boolean strict) {
+ public void set(final long key, final Object value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final int key, final int value, final boolean strict) {
+ public void set(final int key, final int value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final int key, final long value, final boolean strict) {
+ public void set(final int key, final long value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final int key, final double value, final boolean strict) {
+ public void set(final int key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@Override
- public void set(final int key, final Object value, final boolean strict) {
+ public void set(final int key, final Object value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, strict);
+ super.set(key, value, flags);
} else {
- callAdaptee(__put__, key, value, strict);
+ callAdaptee(__put__, key, value, flags);
}
}
@@ -577,7 +578,7 @@ public final class NativeJSAdapter extends ScriptObject {
}
@Override
- protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+ protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return findHook(desc, __new__, false);
}
@@ -625,8 +626,8 @@ public final class NativeJSAdapter extends ScriptObject {
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
- adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
- testJSAdaptor(adaptee, null, null, null));
+ testJSAdaptor(adaptee, null, null, null),
+ adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
}
}
throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -658,16 +659,16 @@ public final class NativeJSAdapter extends ScriptObject {
return callAdaptee(UNDEFINED, name, args);
}
- private double callAdapteeDouble(final String name, final Object... args) {
- return JSType.toNumber(callAdaptee(name, args));
+ private double callAdapteeDouble(final int programPoint, final String name, final Object... args) {
+ return JSType.toNumberMaybeOptimistic(callAdaptee(name, args), programPoint);
}
- private long callAdapteeLong(final String name, final Object... args) {
- return JSType.toLong(callAdaptee(name, args));
+ private long callAdapteeLong(final int programPoint, final String name, final Object... args) {
+ return JSType.toLongMaybeOptimistic(callAdaptee(name, args), programPoint);
}
- private int callAdapteeInt(final String name, final Object... args) {
- return JSType.toInt32(callAdaptee(name, args));
+ private int callAdapteeInt(final int programPoint, final String name, final Object... args) {
+ return JSType.toInt32MaybeOptimistic(callAdaptee(name, args), programPoint);
}
private Object callAdaptee(final Object retValue, final String name, final Object... args) {
@@ -696,8 +697,8 @@ public final class NativeJSAdapter extends ScriptObject {
if (methodHandle != null) {
return new GuardedInvocation(
methodHandle,
- adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
- testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
+ testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
+ adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
}
}
}
@@ -709,7 +710,7 @@ public final class NativeJSAdapter extends ScriptObject {
final MethodHandle methodHandle = hook.equals(__put__) ?
MH.asType(Lookup.EMPTY_SETTER, type) :
Lookup.emptyGetter(type.returnType());
- return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
+ return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJSON.java b/src/jdk/nashorn/internal/objects/NativeJSON.java
index 344b6da9..7bd8a4a3 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSON.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSON.java
@@ -171,7 +171,7 @@ public final class NativeJSON extends ScriptObject {
}
if (modSpace instanceof Number) {
- int indent = Math.min(10, JSType.toInteger(modSpace));
+ final int indent = Math.min(10, JSType.toInteger(modSpace));
if (indent < 1) {
gap = "";
} else {
@@ -191,7 +191,7 @@ public final class NativeJSON extends ScriptObject {
state.gap = gap;
final ScriptObject wrapper = Global.newEmptyInstance();
- wrapper.set("", value, false);
+ wrapper.set("", value, 0);
return str("", wrapper, state);
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJava.java b/src/jdk/nashorn/internal/objects/NativeJava.java
index 7879bab4..7c6e60a9 100644
--- a/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -36,6 +36,7 @@ import java.util.List;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptUtils;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -44,6 +45,7 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ListAdapter;
import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -80,6 +82,77 @@ public final class NativeJava {
}
/**
+ * Returns synchronized wrapper version of the given ECMAScript function.
+ * @param self not used
+ * @param func the ECMAScript function whose synchronized version is returned.
+ * @param obj the object (i.e, lock) on which the function synchronizes.
+ * @return synchronized wrapper version of the given ECMAScript function.
+ */
+ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
+ if (func instanceof ScriptFunction) {
+ return ((ScriptFunction)func).makeSynchronizedFunction(obj);
+ }
+
+ throw typeError("not.a.function", ScriptRuntime.safeToString(func));
+ }
+
+ /**
+ * Returns true if the specified object is a Java method.
+ * @param self not used
+ * @param obj the object that is checked if it is a Java method object or not
+ * @return tells whether given object is a Java method object or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaMethod(final Object self, final Object obj) {
+ return Bootstrap.isDynamicMethod(obj);
+ }
+
+ /**
+ * Returns true if the specified object is a java function (but not script function)
+ * @param self not used
+ * @param obj the object that is checked if it is a Java function or not
+ * @return tells whether given object is a Java function or not
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaFunction(final Object self, final Object obj) {
+ return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
+ }
+
+ /**
+ * Returns true if the specified object is a Java object but not a script object
+ * @param self not used
+ * @param obj the object that is checked
+ * @return tells whether given object is a Java object but not a script object
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaObject(final Object self, final Object obj) {
+ return obj != null && !(obj instanceof ScriptObject);
+ }
+
+ /**
+ * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
+ * @param self not used
+ * @param obj the object that is checked if it is a ECMAScript object or not
+ * @return tells whether given object is a ECMAScript object or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isScriptObject(final Object self, final Object obj) {
+ return obj instanceof ScriptObject;
+ }
+
+ /**
+ * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
+ * @param self not used
+ * @param obj the object that is checked if it is a ECMAScript function or not
+ * @return tells whether given object is a ECMAScript function or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isScriptFunction(final Object self, final Object obj) {
+ return obj instanceof ScriptFunction;
+ }
+
+ /**
* <p>
* Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
* used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
@@ -414,7 +487,7 @@ public final class NativeJava {
final Context ctx = Global.getThisContext();
try {
return ctx.findClass(typeName);
- } catch(ClassNotFoundException e) {
+ } catch(final ClassNotFoundException e) {
// The logic below compensates for a frequent user error - when people use dot notation to separate inner
// class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
// below will try alternative class names, replacing dots at the end of the name with dollar signs.
@@ -429,7 +502,7 @@ public final class NativeJava {
nextName.setCharAt(lastDot, '$');
try {
return ctx.findClass(nextName.toString());
- } catch(ClassNotFoundException cnfe) {
+ } catch(final ClassNotFoundException cnfe) {
// Intentionally ignored, so the loop retries with the next name
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 40ecbffc..498c263c 100644
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -34,9 +37,12 @@ import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* This is "JavaImporter" constructor. This constructor allows you to use Java types omitting explicit package names.
@@ -91,33 +97,30 @@ public final class NativeJavaImporter extends ScriptObject {
}
/**
- * "No such property" call placeholder.
- *
- * This can never be called as we override {@link ScriptObject#noSuchProperty}. We do declare it here as it's a signal
- * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a {@code noSuchProperty} on this object.
+ * "No such property" handler.
*
* @param self self reference
* @param name property name
- * @return never returns
+ * @return value of the missing property
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object __noSuchProperty__(final Object self, final Object name) {
- throw new AssertionError("__noSuchProperty__ placeholder called");
+ if (! (self instanceof NativeJavaImporter)) {
+ throw typeError("not.a.java.importer", ScriptRuntime.safeToString(self));
+ }
+ return ((NativeJavaImporter)self).createProperty(JSType.toString(name));
}
/**
- * "No such method call" placeholder
- *
- * This can never be called as we override {@link ScriptObject#noSuchMethod}. We do declare it here as it's a signal
- * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a noSuchProperty on this object.
+ * "No such method call" handler
*
* @param self self reference
* @param args arguments to method
- * @return never returns
+ * @return never returns always throw TypeError
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object __noSuchMethod__(final Object self, final Object... args) {
- throw new AssertionError("__noSuchMethod__ placeholder called");
+ throw typeError("not.a.function", ScriptRuntime.safeToString(args[0]));
}
@Override
@@ -131,15 +134,19 @@ public final class NativeJavaImporter extends ScriptObject {
}
@Override
- protected Object invokeNoSuchProperty(final String name) {
- return createProperty(name);
+ protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+ final Object retval = createProperty(name);
+ if (isValid(programPoint)) {
+ throw new UnwarrantedOptimismException(retval, programPoint);
+ }
+ return retval;
}
private boolean createAndSetProperty(final CallSiteDescriptor desc) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Object value = createProperty(name);
if(value != null) {
- set(name, value, false);
+ set(name, value, 0);
return true;
}
return false;
diff --git a/src/jdk/nashorn/internal/objects/NativeMath.java b/src/jdk/nashorn/internal/objects/NativeMath.java
index ec53965a..83b336ca 100644
--- a/src/jdk/nashorn/internal/objects/NativeMath.java
+++ b/src/jdk/nashorn/internal/objects/NativeMath.java
@@ -489,6 +489,20 @@ public final class NativeMath extends ScriptObject {
}
/**
+ * ECMA 15.8.2.11 max(x) - specialized version for two Object args
+ *
+ * @param self self reference
+ * @param x first argument
+ * @param y second argument
+ *
+ * @return largest value of x and y
+ */
+ @SpecializedFunction
+ public static double max(final Object self, final Object x, final Object y) {
+ return Math.max(JSType.toNumber(x), JSType.toNumber(y));
+ }
+
+ /**
* ECMA 15.8.2.12 min(x)
*
* @param self self reference
@@ -567,6 +581,20 @@ public final class NativeMath extends ScriptObject {
}
/**
+ * ECMA 15.8.2.12 min(x) - specialized version for two Object args
+ *
+ * @param self self reference
+ * @param x first argument
+ * @param y second argument
+ *
+ * @return smallest value of x and y
+ */
+ @SpecializedFunction
+ public static double min(final Object self, final Object x, final Object y) {
+ return Math.min(JSType.toNumber(x), JSType.toNumber(y));
+ }
+
+ /**
* ECMA 15.8.2.13 pow(x,y)
*
* @param self self reference
diff --git a/src/jdk/nashorn/internal/objects/NativeNumber.java b/src/jdk/nashorn/internal/objects/NativeNumber.java
index a95587ef..7ea27835 100644
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -25,12 +25,10 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsLong;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -44,6 +42,7 @@ import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -58,9 +57,9 @@ import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
@ScriptClass("Number")
public final class NativeNumber extends ScriptObject {
- // Method handle to create an object wrapper for a primitive number
- private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
- // Method handle to retrieve the Number prototype object
+ /** Method handle to create an object wrapper for a primitive number. */
+ static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
+ /** Method handle to retrieve the Number prototype object. */
private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
/** ECMA 15.7.3.2 largest positive finite value */
@@ -84,8 +83,6 @@ public final class NativeNumber extends ScriptObject {
public static final double POSITIVE_INFINITY = Double.POSITIVE_INFINITY;
private final double value;
- private final boolean isInt;
- private final boolean isLong;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
@@ -93,8 +90,6 @@ public final class NativeNumber extends ScriptObject {
private NativeNumber(final double value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
- this.isInt = isRepresentableAsInt(value);
- this.isLong = isRepresentableAsLong(value);
}
NativeNumber(final double value, final Global global) {
@@ -132,30 +127,6 @@ public final class NativeNumber extends ScriptObject {
return value;
}
- /**
- * Get the value of this Number as a {@code int}
- * @return an {@code int} representing the Number value
- * @throws ClassCastException If number is not representable as an {@code int}
- */
- public int intValue() throws ClassCastException {
- if (isInt) {
- return (int)value;
- }
- throw new ClassCastException();
- }
-
- /**
- * Get the value of this Number as a {@code long}
- * @return a {@code long} representing the Number value
- * @throws ClassCastException If number is not representable as an {@code long}
- */
- public long longValue() throws ClassCastException {
- if (isLong) {
- return (long)value;
- }
- throw new ClassCastException();
- }
-
@Override
public String getClassName() {
return "Number";
@@ -186,8 +157,20 @@ public final class NativeNumber extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String toFixed(final Object self, final Object fractionDigits) {
- final int f = JSType.toInteger(fractionDigits);
- if (f < 0 || f > 20) {
+ return toFixed(self, JSType.toInteger(fractionDigits));
+ }
+
+ /**
+ * ECMA 15.7.4.5 Number.prototype.toFixed (fractionDigits) specialized for int fractionDigits
+ *
+ * @param self self reference
+ * @param fractionDigits how many digits should be after the decimal point, 0 if undefined
+ *
+ * @return number in decimal fixed point notation
+ */
+ @SpecializedFunction
+ public static String toFixed(final Object self, final int fractionDigits) {
+ if (fractionDigits < 0 || fractionDigits > 20) {
throw rangeError("invalid.fraction.digits", "toFixed");
}
@@ -201,8 +184,8 @@ public final class NativeNumber extends ScriptObject {
}
final NumberFormat format = NumberFormat.getNumberInstance(Locale.US);
- format.setMinimumFractionDigits(f);
- format.setMaximumFractionDigits(f);
+ format.setMinimumFractionDigits(fractionDigits);
+ format.setMaximumFractionDigits(fractionDigits);
format.setGroupingUsed(false);
return format.format(x);
@@ -240,7 +223,7 @@ public final class NativeNumber extends ScriptObject {
* ECMA 15.7.4.7 Number.prototype.toPrecision (precision)
*
* @param self self reference
- * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link NativeDate#toString} if undefined
+ * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link JSType#toString} if undefined
*
* @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
*/
@@ -250,8 +233,23 @@ public final class NativeNumber extends ScriptObject {
if (precision == UNDEFINED) {
return JSType.toString(x);
}
+ return (toPrecision(x, JSType.toInteger(precision)));
+ }
+
+ /**
+ * ECMA 15.7.4.7 Number.prototype.toPrecision (precision) specialized f
+ *
+ * @param self self reference
+ * @param precision use {@code precision - 1} digits after the significand's decimal point.
+ *
+ * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
+ */
+ @SpecializedFunction
+ public static String toPrecision(final Object self, final int precision) {
+ return toPrecision(getNumberValue(self), precision);
+ }
- final int p = JSType.toInteger(precision);
+ private static String toPrecision(final double x, final int p) {
if (Double.isNaN(x)) {
return "NaN";
} else if (Double.isInfinite(x)) {
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index 4fd8aeb5..c086442d 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -75,7 +75,10 @@ import jdk.nashorn.internal.runtime.linker.NashornBeansLinker;
*/
@ScriptClass("Object")
public final class NativeObject {
+ /** Methodhandle to proto getter */
public static final MethodHandle GET__PROTO__ = findOwnMH("get__proto__", ScriptObject.class, Object.class);
+
+ /** Methodhandle to proto setter */
public static final MethodHandle SET__PROTO__ = findOwnMH("set__proto__", Object.class, Object.class, Object.class);
private static final Object TO_STRING = new Object();
@@ -94,9 +97,7 @@ public final class NativeObject {
private static ScriptObject get__proto__(final Object self) {
// See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__
// Step 1 Let O be the result of calling ToObject passing the this.
- final Object obj = Global.toObject(self);
- Global.checkObject(obj);
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(Global.toObject(self));
return sobj.getProto();
}
@@ -282,8 +283,7 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
- Global.checkObject(obj);
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(obj);
sobj.defineOwnProperty(JSType.toString(prop), attr, true);
return sobj;
}
@@ -298,9 +298,7 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
- Global.checkObject(obj);
-
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(obj);
final Object propsObj = Global.toObject(props);
if (propsObj instanceof ScriptObject) {
@@ -454,18 +452,17 @@ public final class NativeObject {
*/
@Constructor
public static Object construct(final boolean newObj, final Object self, final Object value) {
- final JSType type = JSType.of(value);
+ final JSType type = JSType.ofNoFunction(value);
// Object(null), Object(undefined), Object() are same as "new Object()"
- if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) {
+ if (newObj || type == JSType.NULL || type == JSType.UNDEFINED) {
switch (type) {
case BOOLEAN:
case NUMBER:
case STRING:
return Global.toObject(value);
case OBJECT:
- case FUNCTION:
return value;
case NULL:
case UNDEFINED:
@@ -546,7 +543,7 @@ public final class NativeObject {
final Object key = JSType.toPrimitive(v, String.class);
final Object obj = Global.toObject(self);
- return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(key);
+ return obj instanceof ScriptObject && ((ScriptObject)obj).hasOwnProperty(key);
}
/**
@@ -660,25 +657,29 @@ public final class NativeObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object bindProperties(final Object self, final Object target, final Object source) {
// target object has to be a ScriptObject
- Global.checkObject(target);
+ final ScriptObject targetObj = Global.checkObject(target);
// check null or undefined source object
Global.checkObjectCoercible(source);
- final ScriptObject targetObj = (ScriptObject)target;
-
if (source instanceof ScriptObject) {
- final ScriptObject sourceObj = (ScriptObject)source;
- final Property[] properties = sourceObj.getMap().getProperties();
+ final ScriptObject sourceObj = (ScriptObject)source;
+
+ final PropertyMap sourceMap = sourceObj.getMap();
+ final Property[] properties = sourceMap.getProperties();
+ //replace the map and blow up everything to objects to work with dual fields :-(
// filter non-enumerable properties
final ArrayList<Property> propList = new ArrayList<>();
- for (Property prop : properties) {
+ for (final Property prop : properties) {
if (prop.isEnumerable()) {
+ final Object value = sourceObj.get(prop.getKey());
+ prop.setType(Object.class);
+ prop.setValue(sourceObj, sourceObj, value, false);
propList.add(prop);
}
}
- if (! propList.isEmpty()) {
+ if (!propList.isEmpty()) {
targetObj.addBoundProperties(sourceObj, propList.toArray(new Property[propList.size()]));
}
} else if (source instanceof ScriptObjectMirror) {
@@ -696,7 +697,7 @@ public final class NativeObject {
final String name = keys[idx];
final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
- props[idx] = (AccessorProperty.create(name, 0, getter, setter));
+ props[idx] = AccessorProperty.create(name, 0, getter, setter);
}
targetObj.addBoundProperties(source, props);
@@ -715,6 +716,32 @@ public final class NativeObject {
return target;
}
+ /**
+ * Binds the source mirror object's properties to the target object. Binding
+ * properties allows two-way read/write for the properties of the source object.
+ * All inherited, enumerable properties are also bound. This method is used to
+ * to make 'with' statement work with ScriptObjectMirror as scope object.
+ *
+ * @param target the target object to which the source object's properties are bound
+ * @param source the source object whose properties are bound to the target
+ * @return the target object after property binding
+ */
+ public static Object bindAllProperties(final ScriptObject target, final ScriptObjectMirror source) {
+ final Set<String> keys = source.keySet();
+ // make accessor properties using dynamic invoker getters and setters
+ final AccessorProperty[] props = new AccessorProperty[keys.size()];
+ int idx = 0;
+ for (final String name : keys) {
+ final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
+ final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
+ props[idx] = AccessorProperty.create(name, 0, getter, setter);
+ idx++;
+ }
+
+ target.addBoundProperties(source, props);
+ return target;
+ }
+
private static void bindBeanProperties(final ScriptObject targetObj, final Object source,
final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames,
final Collection<String> methodNames) {
@@ -772,16 +799,16 @@ public final class NativeObject {
targetObj.addBoundProperties(source, properties.toArray(new AccessorProperty[properties.size()]));
}
- private static MethodHandle getBoundBeanMethodGetter(Object source, MethodHandle methodGetter) {
+ private static MethodHandle getBoundBeanMethodGetter(final Object source, final MethodHandle methodGetter) {
try {
// NOTE: we're relying on the fact that "dyn:getMethod:..." return value is constant for any given method
// name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is
// constant for any given method name and object's class.)
return MethodHandles.dropArguments(MethodHandles.constant(Object.class,
- Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class);
+ Bootstrap.bindCallable(methodGetter.invoke(source), source, null)), 0, Object.class);
} catch(RuntimeException|Error e) {
throw e;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
@@ -794,10 +821,10 @@ public final class NativeObject {
assert passesGuard(source, inv.getGuard());
} catch(RuntimeException|Error e) {
throw e;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
- assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints.
+ assert inv.getSwitchPoints() == null; // Linkers in Dynalink's beans package don't use switchpoints.
// We discard the guard, as all method handles will be bound to a specific object.
return inv.getInvocation();
}
@@ -806,12 +833,12 @@ public final class NativeObject {
return guard == null || (boolean)guard.invoke(obj);
}
- private static LinkRequest createLinkRequest(String operation, MethodType methodType, Object source) {
+ private static LinkRequest createLinkRequest(final String operation, final MethodType methodType, final Object source) {
return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation,
- methodType), false, source);
+ methodType), null, 0, false, source);
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
+ return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExp.java b/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 34657d25..33ef2849 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -28,9 +28,11 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Callable;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -38,19 +40,20 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.BitVector;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.regexp.RegExp;
-import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
-import jdk.nashorn.internal.runtime.regexp.RegExpResult;
-import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.regexp.RegExp;
+import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
+import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
+import jdk.nashorn.internal.runtime.regexp.RegExpResult;
/**
* ECMA 15.10 RegExp Objects.
@@ -141,7 +144,7 @@ public final class NativeRegExp extends ScriptObject {
* @param self self reference
* @return new NativeRegExp
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeRegExp constructor(final boolean isNew, final Object self) {
return new NativeRegExp("", "");
}
@@ -156,7 +159,7 @@ public final class NativeRegExp extends ScriptObject {
* @param pattern pattern
* @return new NativeRegExp
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) {
return newRegExp(pattern, UNDEFINED);
}
@@ -172,7 +175,7 @@ public final class NativeRegExp extends ScriptObject {
* @param flags flags
* @return new NativeRegExp
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
return newRegExp(pattern, flags);
}
@@ -211,7 +214,7 @@ public final class NativeRegExp extends ScriptObject {
* @param string pattern string
* @return flat regexp
*/
- static NativeRegExp flatRegExp(String string) {
+ static NativeRegExp flatRegExp(final String string) {
// escape special characters
StringBuilder sb = null;
final int length = string.length();
@@ -379,7 +382,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "input")
- public static Object getLastInput(Object self) {
+ public static Object getLastInput(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getInput();
}
@@ -390,7 +393,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "multiline")
- public static Object getLastMultiline(Object self) {
+ public static Object getLastMultiline(final Object self) {
return false; // doesn't ever seem to become true and isn't documented anyhwere
}
@@ -400,7 +403,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "lastMatch")
- public static Object getLastMatch(Object self) {
+ public static Object getLastMatch(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(0);
}
@@ -411,7 +414,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "lastParen")
- public static Object getLastParen(Object self) {
+ public static Object getLastParen(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getLastParen();
}
@@ -422,7 +425,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "leftContext")
- public static Object getLeftContext(Object self) {
+ public static Object getLeftContext(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getInput().substring(0, match.getIndex());
}
@@ -433,7 +436,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "rightContext")
- public static Object getRightContext(Object self) {
+ public static Object getRightContext(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getInput().substring(match.getIndex() + match.length());
}
@@ -444,7 +447,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$1")
- public static Object getGroup1(Object self) {
+ public static Object getGroup1(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(1);
}
@@ -455,7 +458,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$2")
- public static Object getGroup2(Object self) {
+ public static Object getGroup2(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(2);
}
@@ -466,7 +469,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$3")
- public static Object getGroup3(Object self) {
+ public static Object getGroup3(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(3);
}
@@ -477,7 +480,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$4")
- public static Object getGroup4(Object self) {
+ public static Object getGroup4(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(4);
}
@@ -488,7 +491,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$5")
- public static Object getGroup5(Object self) {
+ public static Object getGroup5(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(5);
}
@@ -499,7 +502,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$6")
- public static Object getGroup6(Object self) {
+ public static Object getGroup6(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(6);
}
@@ -510,7 +513,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$7")
- public static Object getGroup7(Object self) {
+ public static Object getGroup7(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(7);
}
@@ -521,7 +524,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$8")
- public static Object getGroup8(Object self) {
+ public static Object getGroup8(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(8);
}
@@ -532,7 +535,7 @@ public final class NativeRegExp extends ScriptObject {
* @return last regexp input
*/
@Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$9")
- public static Object getGroup9(Object self) {
+ public static Object getGroup9(final Object self) {
final RegExpResult match = Global.instance().getLastRegExpResult();
return match == null ? "" : match.getGroup(9);
}
@@ -569,7 +572,7 @@ public final class NativeRegExp extends ScriptObject {
}
// String.prototype.split method ignores the global flag and should not update lastIndex property.
- private RegExpResult execSplit(final String string, int start) {
+ private RegExpResult execSplit(final String string, final int start) {
if (start < 0 || start > string.length()) {
return null;
}
@@ -596,7 +599,7 @@ public final class NativeRegExp extends ScriptObject {
for (int i = 0, lastGroupStart = matcher.start(); i <= groupCount; i++) {
final int groupStart = matcher.start(i);
if (lastGroupStart > groupStart
- || (groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i))) {
+ || groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i)) {
// (1) ECMA 15.10.2.5 NOTE 3: need to clear Atom's captures each time Atom is repeated.
// (2) ECMA 15.10.2.8 NOTE 3: Backreferences to captures in (?!Disjunction) from elsewhere
// in the pattern always return undefined because the negative lookahead must fail.
@@ -649,7 +652,7 @@ public final class NativeRegExp extends ScriptObject {
* @param replacement Replacement string.
* @return String with substitutions.
*/
- String replace(final String string, final String replacement, final ScriptFunction function) {
+ String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable {
final RegExpMatcher matcher = regexp.match(string);
if (matcher == null) {
@@ -665,7 +668,8 @@ public final class NativeRegExp extends ScriptObject {
sb.append(string, 0, matcher.start());
if (function != null) {
- sb.append(callReplaceValue(function, matcher, string));
+ final Object self = function.isStrict() ? UNDEFINED : Global.instance();
+ sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
}
@@ -683,10 +687,13 @@ public final class NativeRegExp extends ScriptObject {
int previousLastIndex = 0;
final StringBuilder sb = new StringBuilder();
+ final MethodHandle invoker = function == null ? null : getReplaceValueInvoker();
+ final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance();
+
do {
sb.append(string, thisIndex, matcher.start());
if (function != null) {
- sb.append(callReplaceValue(function, matcher, string));
+ sb.append(callReplaceValue(invoker, function, self, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
}
@@ -746,8 +753,8 @@ public final class NativeRegExp extends ScriptObject {
cursor++;
if (cursor < replacement.length() && firstDigit < matcher.groupCount()) {
final int secondDigit = replacement.charAt(cursor) - '0';
- if ((secondDigit >= 0) && (secondDigit <= 9)) {
- final int newRefNum = (firstDigit * 10) + secondDigit;
+ if (secondDigit >= 0 && secondDigit <= 9) {
+ final int newRefNum = firstDigit * 10 + secondDigit;
if (newRefNum <= matcher.groupCount() && newRefNum > 0) {
// $nn ($01-$99)
refNum = newRefNum;
@@ -790,16 +797,26 @@ public final class NativeRegExp extends ScriptObject {
}
}
- private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) {
+ private static final Object REPLACE_VALUE = new Object();
+
+ private static final MethodHandle getReplaceValueInvoker() {
+ return Global.instance().getDynamicInvoker(REPLACE_VALUE,
+ new Callable<MethodHandle>() {
+ @Override
+ public MethodHandle call() {
+ return Bootstrap.createDynamicInvoker("dyn:call", String.class, ScriptFunction.class, Object.class, Object[].class);
+ }
+ });
+ }
+
+ private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable {
final Object[] groups = groups(matcher);
final Object[] args = Arrays.copyOf(groups, groups.length + 2);
args[groups.length] = matcher.start();
args[groups.length + 1] = string;
- final Object self = function.isStrict() ? UNDEFINED : Global.instance();
-
- return JSType.toString(ScriptRuntime.apply(function, self, args));
+ return (String)invoker.invokeExact(function, self, args);
}
/**
@@ -908,7 +925,6 @@ public final class NativeRegExp extends ScriptObject {
}
private static NativeRegExp checkRegExp(final Object self) {
- Global.checkObjectCoercible(self);
if (self instanceof NativeRegExp) {
return (NativeRegExp)self;
} else if (self != null && self == Global.instance().getRegExpPrototype()) {
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
index f12cea12..467399ae 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
@@ -32,9 +32,9 @@ import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Setter;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.regexp.RegExpResult;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.regexp.RegExpResult;
/**
* Objects of this class are used to represent return values from
@@ -74,7 +74,7 @@ public final class NativeRegExpExecResult extends ScriptObject {
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static Object length(final Object self) {
if (self instanceof ScriptObject) {
- return ((ScriptObject)self).getArray().length() & JSType.MAX_UINT;
+ return JSType.toUint32(((ScriptObject)self).getArray().length());
}
return 0;
diff --git a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
index dd2c2816..7f32c10f 100644
--- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
+++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
@@ -25,8 +25,8 @@
package jdk.nashorn.internal.objects;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -79,8 +79,9 @@ public final class NativeStrictArguments extends ScriptObject {
final ScriptFunction func = Global.instance().getTypeErrorThrower();
// We have to fill user accessor functions late as these are stored
// in this object rather than in the PropertyMap of this object.
- setUserAccessors("caller", func, func);
- setUserAccessors("callee", func, func);
+ final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+ initUserAccessors("caller", flags, func, func);
+ initUserAccessors("callee", flags, func, func);
setArray(ArrayData.allocate(values));
this.length = values.length;
diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java
index 51edf75a..7fb86a4a 100644
--- a/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/src/jdk/nashorn/internal/objects/NativeString.java
@@ -39,6 +39,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -48,11 +49,12 @@ import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.OptimisticBuiltins;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -66,13 +68,13 @@ import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
* ECMA 15.5 String Objects.
*/
@ScriptClass("String")
-public final class NativeString extends ScriptObject {
+public final class NativeString extends ScriptObject implements OptimisticBuiltins {
private final CharSequence value;
- // Method handle to create an object wrapper for a primitive string
- private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
- // Method handle to retrieve the String prototype object
+ /** Method handle to create an object wrapper for a primitive string */
+ static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
+ /** Method handle to retrieve the String prototype object */
private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
@@ -155,10 +157,9 @@ public final class NativeString extends ScriptObject {
if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
try {
- MethodHandle mh = MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType());
- return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
+ return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
} catch (final LookupException e) {
- // Shouldn't happen. Fall back to super
+ //empty. Shouldn't happen. Fall back to super
}
}
return super.findGetIndexMethod(desc, request);
@@ -236,111 +237,111 @@ public final class NativeString extends ScriptObject {
}
@Override
- public int getInt(final Object key) {
- return JSType.toInt32(get(key));
+ public int getInt(final Object key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final double key) {
- return JSType.toInt32(get(key));
+ public int getInt(final double key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final long key) {
- return JSType.toInt32(get(key));
+ public int getInt(final long key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final int key) {
- return JSType.toInt32(get(key));
+ public int getInt(final int key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final Object key) {
- return JSType.toUint32(get(key));
+ public long getLong(final Object key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final double key) {
- return JSType.toUint32(get(key));
+ public long getLong(final double key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final long key) {
- return JSType.toUint32(get(key));
+ public long getLong(final long key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final int key) {
- return JSType.toUint32(get(key));
+ public long getLong(final int key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final Object key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final Object key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final double key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final double key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final long key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final long key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final int key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final int key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
public boolean has(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
final int index = ArrayIndex.getArrayIndex(primitiveKey);
- return isValid(index) || super.has(primitiveKey);
+ return isValidStringIndex(index) || super.has(primitiveKey);
}
@Override
public boolean has(final int key) {
- return isValid(key) || super.has(key);
+ return isValidStringIndex(key) || super.has(key);
}
@Override
public boolean has(final long key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.has(key);
+ return isValidStringIndex(index) || super.has(key);
}
@Override
public boolean has(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.has(key);
+ return isValidStringIndex(index) || super.has(key);
}
@Override
public boolean hasOwnProperty(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
final int index = ArrayIndex.getArrayIndex(primitiveKey);
- return isValid(index) || super.hasOwnProperty(primitiveKey);
+ return isValidStringIndex(index) || super.hasOwnProperty(primitiveKey);
}
@Override
public boolean hasOwnProperty(final int key) {
- return isValid(key) || super.hasOwnProperty(key);
+ return isValidStringIndex(key) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final long key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.hasOwnProperty(key);
+ return isValidStringIndex(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.hasOwnProperty(key);
+ return isValidStringIndex(index) || super.hasOwnProperty(key);
}
@Override
@@ -368,7 +369,7 @@ public final class NativeString extends ScriptObject {
}
private boolean checkDeleteIndex(final int index, final boolean strict) {
- if (isValid(index)) {
+ if (isValidStringIndex(index)) {
if (strict) {
throw typeError("cant.delete.property", Integer.toString(index), ScriptRuntime.safeToString(this));
}
@@ -392,10 +393,12 @@ public final class NativeString extends ScriptObject {
/**
* return a List of own keys associated with the object.
* @param all True if to include non-enumerable keys.
+ * @param nonEnumerable set of non-enumerable properties seen already.Used
+ * to filter out shadowed, but enumerable properties from proto children.
* @return Array of keys.
*/
@Override
- public String[] getOwnKeys(final boolean all) {
+ protected String[] getOwnKeys(final boolean all, final Set<String> nonEnumerable) {
final List<Object> keys = new ArrayList<>();
// add string index keys
@@ -404,7 +407,7 @@ public final class NativeString extends ScriptObject {
}
// add super class properties
- keys.addAll(Arrays.asList(super.getOwnKeys(all)));
+ keys.addAll(Arrays.asList(super.getOwnKeys(all, nonEnumerable)));
return keys.toArray(new String[keys.size()]);
}
@@ -441,12 +444,11 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static String fromCharCode(final Object self, final Object value) {
- try {
- return "" + (char)JSType.toUint16(((Number)value).doubleValue());
- } catch (final ClassCastException e) {
- return fromCharCode(self, new Object[] { value });
+ public static Object fromCharCode(final Object self, final Object value) {
+ if (value instanceof Integer) {
+ return fromCharCode(self, (int)value);
}
+ return Character.toString((char)JSType.toUint16(value));
}
/**
@@ -457,18 +459,46 @@ public final class NativeString extends ScriptObject {
*/
@SpecializedFunction
public static String fromCharCode(final Object self, final int value) {
- return "" + (char)(value & 0xffff);
+ return Character.toString((char)(value & 0xffff));
}
/**
- * ECMA 15.5.3.2 - specialization for one char of long type
+ * ECMA 15.5.3.2 - specialization for two chars of int type
* @param self self reference
- * @param value one argument to be interpreted as char
+ * @param ch1 first char
+ * @param ch2 second char
+ * @return string with one charcode
+ */
+ @SpecializedFunction
+ public static Object fromCharCode(final Object self, final int ch1, final int ch2) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff));
+ }
+
+ /**
+ * ECMA 15.5.3.2 - specialization for three chars of int type
+ * @param self self reference
+ * @param ch1 first char
+ * @param ch2 second char
+ * @param ch3 third char
* @return string with one charcode
*/
@SpecializedFunction
- public static String fromCharCode(final Object self, final long value) {
- return "" + (char)((int)value & 0xffff);
+ public static Object fromCharCode(final Object self, final int ch1, final int ch2, final int ch3) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff));
+ }
+
+ /**
+ * ECMA 15.5.3.2 - specialization for four chars of int type
+ * @param self self reference
+ * @param ch1 first char
+ * @param ch2 second char
+ * @param ch3 third char
+ * @param ch4 fourth char
+ * @return string with one charcode
+ */
+ @SpecializedFunction
+ public static String fromCharCode(final Object self, final int ch1, final int ch2, final int ch3, final int ch4) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff)) + Character.toString((char)(ch4 & 0xffff));
}
/**
@@ -479,7 +509,7 @@ public final class NativeString extends ScriptObject {
*/
@SpecializedFunction
public static String fromCharCode(final Object self, final double value) {
- return "" + (char)JSType.toUint16(value);
+ return Character.toString((char)JSType.toUint16(value));
}
/**
@@ -536,7 +566,15 @@ public final class NativeString extends ScriptObject {
}
private static String charAtImpl(final String str, final int pos) {
- return (pos < 0 || pos >= str.length()) ? "" : String.valueOf(str.charAt(pos));
+ return pos < 0 || pos >= str.length() ? "" : String.valueOf(str.charAt(pos));
+ }
+
+ private static int getValidChar(final Object self, final int pos) {
+ try {
+ return ((CharSequence)self).charAt(pos);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //invalid char, out of bounds, force relink
+ }
}
/**
@@ -547,7 +585,9 @@ public final class NativeString extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static double charCodeAt(final Object self, final Object pos) {
- return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos));
+ final String str = checkObjectToString(self);
+ final int idx = JSType.toInteger(pos);
+ return idx < 0 || idx >= str.length() ? Double.NaN : str.charAt(idx);
}
/**
@@ -556,24 +596,32 @@ public final class NativeString extends ScriptObject {
* @param pos position in string
* @return number representing charcode at position
*/
- @SpecializedFunction
- public static double charCodeAt(final Object self, final double pos) {
- return charCodeAt(self, (int) pos);
+ @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class)
+ public static int charCodeAt(final Object self, final double pos) {
+ return charCodeAt(self, (int)pos); //toInt pos is ok
}
/**
- * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for int position
+ * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for long position
* @param self self reference
* @param pos position in string
* @return number representing charcode at position
*/
- @SpecializedFunction
- public static double charCodeAt(final Object self, final int pos) {
- return charCodeAtImpl(checkObjectToString(self), pos);
+ @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class)
+ public static int charCodeAt(final Object self, final long pos) {
+ return charCodeAt(self, (int)pos);
}
- private static double charCodeAtImpl(final String str, final int pos) {
- return (pos < 0 || pos >= str.length()) ? Double.NaN : str.charAt(pos);
+ /**
+ * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for int position
+ * @param self self reference
+ * @param pos position in string
+ * @return number representing charcode at position
+ */
+
+ @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class)
+ public static int charCodeAt(final Object self, final int pos) {
+ return getValidChar(self, pos);
}
/**
@@ -688,7 +736,7 @@ public final class NativeString extends ScriptObject {
collator.setStrength(Collator.IDENTICAL);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
- return (double)collator.compare(str, JSType.toString(that));
+ return collator.compare(str, JSType.toString(that));
}
/**
@@ -743,9 +791,10 @@ public final class NativeString extends ScriptObject {
* @param string item to replace
* @param replacement item to replace it with
* @return string after replacement
+ * @throws Throwable if replacement fails
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String replace(final Object self, final Object string, final Object replacement) {
+ public static String replace(final Object self, final Object string, final Object replacement) throws Throwable {
final String str = checkObjectToString(self);
@@ -807,7 +856,7 @@ public final class NativeString extends ScriptObject {
@SpecializedFunction
public static String slice(final Object self, final int start) {
final String str = checkObjectToString(self);
- final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
+ final int from = start < 0 ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
return str.substring(from);
}
@@ -838,8 +887,8 @@ public final class NativeString extends ScriptObject {
final String str = checkObjectToString(self);
final int len = str.length();
- final int from = (start < 0) ? Math.max(len + start, 0) : Math.min(start, len);
- final int to = (end < 0) ? Math.max(len + end, 0) : Math.min(end, len);
+ final int from = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
+ final int to = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
return str.substring(Math.min(from, to), to);
}
@@ -868,7 +917,7 @@ public final class NativeString extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static ScriptObject split(final Object self, final Object separator, final Object limit) {
final String str = checkObjectToString(self);
- final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
+ final long lim = limit == UNDEFINED ? JSType.MAX_UINT : JSType.toUint32(limit);
if (separator == UNDEFINED) {
return lim == 0 ? new NativeArray() : new NativeArray(new Object[]{str});
@@ -882,7 +931,7 @@ public final class NativeString extends ScriptObject {
return splitString(str, JSType.toString(separator), lim);
}
- private static ScriptObject splitString(String str, String separator, long limit) {
+ private static ScriptObject splitString(final String str, final String separator, final long limit) {
if (separator.isEmpty()) {
final int length = (int) Math.min(str.length(), limit);
final Object[] array = new Object[length];
@@ -899,7 +948,7 @@ public final class NativeString extends ScriptObject {
int n = 0;
while (pos < strLength && n < limit) {
- int found = str.indexOf(separator, pos);
+ final int found = str.indexOf(separator, pos);
if (found == -1) {
break;
}
@@ -932,7 +981,7 @@ public final class NativeString extends ScriptObject {
intStart = Math.max(intStart + strLength, 0);
}
- final int intLen = Math.min(Math.max((length == UNDEFINED) ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
+ final int intLen = Math.min(Math.max(length == UNDEFINED ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
return intLen <= 0 ? "" : str.substring(intStart, intStart + intLen);
}
@@ -998,8 +1047,8 @@ public final class NativeString extends ScriptObject {
public static String substring(final Object self, final int start, final int end) {
final String str = checkObjectToString(self);
final int len = str.length();
- final int validStart = start < 0 ? 0 : (start > len ? len : start);
- final int validEnd = end < 0 ? 0 : (end > len ? len : end);
+ final int validStart = start < 0 ? 0 : start > len ? len : start;
+ final int validEnd = end < 0 ? 0 : end > len ? len : end;
if (validStart < validEnd) {
return str.substring(validStart, validEnd);
@@ -1067,7 +1116,6 @@ public final class NativeString extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String trim(final Object self) {
-
final String str = checkObjectToString(self);
int start = 0;
int end = str.length() - 1;
@@ -1092,7 +1140,7 @@ public final class NativeString extends ScriptObject {
final String str = checkObjectToString(self);
int start = 0;
- int end = str.length() - 1;
+ final int end = str.length() - 1;
while (start <= end && ScriptRuntime.isJSWhitespace(str.charAt(start))) {
start++;
@@ -1110,7 +1158,7 @@ public final class NativeString extends ScriptObject {
public static String trimRight(final Object self) {
final String str = checkObjectToString(self);
- int start = 0;
+ final int start = 0;
int end = str.length() - 1;
while (end >= start && ScriptRuntime.isJSWhitespace(str.charAt(end))) {
@@ -1120,7 +1168,7 @@ public final class NativeString extends ScriptObject {
return str.substring(start, end + 1);
}
- private static ScriptObject newObj(final Object self, final CharSequence str) {
+ private static ScriptObject newObj(final CharSequence str) {
return new NativeString(str);
}
@@ -1137,8 +1185,8 @@ public final class NativeString extends ScriptObject {
*/
@Constructor(arity = 1)
public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- final CharSequence str = (args.length > 0) ? JSType.toCharSequence(args[0]) : "";
- return newObj ? newObj(self, str) : str.toString();
+ final CharSequence str = args.length > 0 ? JSType.toCharSequence(args[0]) : "";
+ return newObj ? newObj(str) : str.toString();
}
/**
@@ -1151,9 +1199,9 @@ public final class NativeString extends ScriptObject {
*
* @return new NativeString ("")
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static Object constructor(final boolean newObj, final Object self) {
- return newObj ? newObj(self, "") : "";
+ return newObj ? newObj("") : "";
}
/**
@@ -1167,10 +1215,10 @@ public final class NativeString extends ScriptObject {
*
* @return new NativeString (arg)
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static Object constructor(final boolean newObj, final Object self, final Object arg) {
final CharSequence str = JSType.toCharSequence(arg);
- return newObj ? newObj(self, str) : str.toString();
+ return newObj ? newObj(str) : str.toString();
}
/**
@@ -1184,10 +1232,61 @@ public final class NativeString extends ScriptObject {
*
* @return new NativeString containing the string representation of the arg
*/
- @SpecializedConstructor
+ @SpecializedFunction(isConstructor=true)
public static Object constructor(final boolean newObj, final Object self, final int arg) {
+ final String str = Integer.toString(arg);
+ return newObj ? newObj(str) : str;
+ }
+
+ /**
+ * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg
+ *
+ * Constructor
+ *
+ * @param newObj is this constructor invoked with the new operator
+ * @param self self reference
+ * @param arg the arg
+ *
+ * @return new NativeString containing the string representation of the arg
+ */
+ @SpecializedFunction(isConstructor=true)
+ public static Object constructor(final boolean newObj, final Object self, final long arg) {
+ final String str = Long.toString(arg);
+ return newObj ? newObj(str) : str;
+ }
+
+ /**
+ * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg
+ *
+ * Constructor
+ *
+ * @param newObj is this constructor invoked with the new operator
+ * @param self self reference
+ * @param arg the arg
+ *
+ * @return new NativeString containing the string representation of the arg
+ */
+ @SpecializedFunction(isConstructor=true)
+ public static Object constructor(final boolean newObj, final Object self, final double arg) {
final String str = JSType.toString(arg);
- return newObj ? newObj(self, str) : str;
+ return newObj ? newObj(str) : str;
+ }
+
+ /**
+ * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code boolean} arg
+ *
+ * Constructor
+ *
+ * @param newObj is this constructor invoked with the new operator
+ * @param self self reference
+ * @param arg the arg
+ *
+ * @return new NativeString containing the string representation of the arg
+ */
+ @SpecializedFunction(isConstructor=true)
+ public static Object constructor(final boolean newObj, final Object self, final boolean arg) {
+ final String str = Boolean.toString(arg);
+ return newObj ? newObj(str) : str;
}
/**
@@ -1234,7 +1333,7 @@ public final class NativeString extends ScriptObject {
} else if (self != null && self == Global.instance().getStringPrototype()) {
return "";
} else {
- throw typeError( "not.a.string", ScriptRuntime.safeToString(self));
+ throw typeError("not.a.string", ScriptRuntime.safeToString(self));
}
}
@@ -1255,11 +1354,57 @@ public final class NativeString extends ScriptObject {
}
}
- private boolean isValid(final int key) {
+ private boolean isValidStringIndex(final int key) {
return key >= 0 && key < value.length();
}
private static MethodHandle findOwnMH(final String name, final MethodType type) {
return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type);
}
+
+ @Override
+ public LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) {
+ if (clazz == CharCodeAtLinkLogic.class) {
+ return CharCodeAtLinkLogic.INSTANCE;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasPerInstanceAssumptions() {
+ return false;
+ }
+
+ /**
+ * This is linker logic charCodeAt - when we specialize further methods in NativeString
+ * It may be expanded. It's link check makes sure that we are dealing with a char
+ * sequence and that we are in range
+ */
+ private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic {
+ private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic();
+
+ @Override
+ public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ try {
+ //check that it's a char sequence or throw cce
+ final CharSequence cs = (CharSequence)self;
+ //check that the index, representable as an int, is inside the array
+ final int intIndex = JSType.toInteger(request.getArguments()[2]);
+ return intIndex >= 0 && intIndex < cs.length(); //can link
+ } catch (final ClassCastException | IndexOutOfBoundsException e) {
+ //fallthru
+ }
+ return false;
+ }
+
+ /**
+ * charCodeAt callsites can throw ClassCastException as a mechanism to have them
+ * relinked - this enabled fast checks of the kind of ((IntArrayData)arrayData).push(x)
+ * for an IntArrayData only push - if this fails, a CCE will be thrown and we will relink
+ */
+ @Override
+ public Class<? extends Throwable> getRelinkException() {
+ return ClassCastException.class;
+ }
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index 8aa3d628..2fc2c51a 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint16 array for TypedArray extension
@@ -55,37 +63,125 @@ public final class NativeUint16Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint16Array(buffer, byteOffset, length);
}
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint16ArrayData(buffer, byteOffset, length);
+ public Uint16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint16ArrayData(nb.asCharBuffer(), start, end);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Uint16Array";
}
};
- private static final class Uint16ArrayData extends ArrayDataImpl {
- private Uint16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint16ArrayData extends TypedArrayData<CharBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint16ArrayData(final CharBuffer nb, final int start, final int end) {
+ super(((CharBuffer)nb.position(start).limit(end)).slice(), end - start);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (char)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 ;
+ public boolean isUnsigned() {
+ return true;
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -100,7 +196,7 @@ public final class NativeUint16Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint16Array)constructorImpl(args, FACTORY);
+ return (NativeUint16Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -108,11 +204,6 @@ public final class NativeUint16Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint16Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 73812246..4c83cc01 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -25,6 +25,13 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint32 array for TypedArray extension
@@ -56,55 +64,128 @@ public final class NativeUint32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteBegin, final int length) {
return new NativeUint32Array(buffer, byteBegin, length);
}
+
+ @Override
+ public Uint32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint32ArrayData(nb.order(ByteOrder.nativeOrder()).asIntBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint32ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint32Array";
}
};
- private static final class Uint32ArrayData extends ArrayDataImpl {
- private Uint32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint32ArrayData extends TypedArrayData<IntBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", long.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint32ArrayData(final IntBuffer nb, final int start, final int end) {
+ super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
+ }
+
+ private long getElem(final int index) {
+ try {
+ return JSType.toUint32(nb.get(index));
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return long.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return (int)getLong(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public double getDouble(final int index) {
+ return getLong(index);
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getLong(index);
}
@Override
- protected long getLongImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public Object getObject(final int index) {
+ return getLong(index);
}
@Override
- protected double getDoubleImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
}
@Override
- protected Object getObjectImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -119,7 +200,7 @@ public final class NativeUint32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint32Array)constructorImpl(args, FACTORY);
+ return (NativeUint32Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +208,6 @@ public final class NativeUint32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 1f304563..6e69ebad 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -25,21 +25,29 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint8 array for TypedArray extension
*/
@ScriptClass("Uint8Array")
public final class NativeUint8Array extends ArrayBufferView {
+
/**
* The size in bytes of each element in the array.
*/
@@ -55,31 +63,127 @@ public final class NativeUint8Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint8Array(buffer, byteOffset, length);
}
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint8ArrayData(buffer, byteOffset, length);
+ public Uint8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint8ArrayData(nb, start, end);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Uint8Array";
}
};
- private static final class Uint8ArrayData extends ArrayDataImpl {
- private Uint8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint8ArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint8ArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index) & 0xff;
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (byte)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return int.class;
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)] & 0xff;
+ public int getInt(final int index) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- buffer.getByteArray()[byteIndex(index)] = (byte)value;
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
}
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
}
/**
@@ -93,7 +197,7 @@ public final class NativeUint8Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint8Array)constructorImpl(args, FACTORY);
+ return (NativeUint8Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -101,11 +205,6 @@ public final class NativeUint8Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint8Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index d69adc10..2dff2612 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -25,6 +25,13 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint8 clamped array for TypedArray extension
@@ -56,55 +64,173 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint8ClampedArray(buffer, byteOffset, length);
}
+
+ @Override
+ public Uint8ClampedArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint8ClampedArrayData(nb, start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint8ClampedArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint8ClampedArray";
}
};
- private static final class Uint8ClampedArrayData extends ArrayDataImpl {
- private Uint8ClampedArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint8ClampedArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+ private static final MethodHandle RINT_D = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle();
+ private static final MethodHandle RINT_O = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", Object.class, Object.class).methodHandle();
+ private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle();
+
+ private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)] & 0xff;
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
}
@Override
- protected void setImpl(final int index, final int value) {
- final byte clamped;
- if ((value & 0xffff_ff00) == 0) {
- clamped = (byte) value;
- } else {
- clamped = value < 0 ? 0 : (byte)0xff;
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return int.class;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index) & 0xff;
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
}
- buffer.getByteArray()[byteIndex(index)] = clamped;
}
@Override
- protected void setImpl(final int index, final long value) {
- if (JSType.isRepresentableAsInt(value)) {
- setImpl(index, (int)value);
- } else {
- buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0;
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ final MethodHandle setter = super.getElementSetter(elementType); //getContinuousElementSetter(getClass(), setElem(), elementType);
+ if (setter != null) {
+ if (elementType == Object.class) {
+ return MH.filterArguments(setter, 2, RINT_O);
+ } else if (elementType == double.class) {
+ return MH.filterArguments(setter, 2, RINT_D);
+ } else if (elementType == long.class) {
+ return MH.filterArguments(setter, 2, CLAMP_LONG);
+ }
+ }
+ return setter;
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ final byte clamped;
+ if ((elem & 0xffff_ff00) == 0) {
+ clamped = (byte)elem;
+ } else {
+ clamped = elem < 0 ? 0 : (byte)0xff;
+ }
+ nb.put(index, clamped);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
}
}
@Override
- protected void setImpl(final int key, final double value) {
- setImpl(key, (int)Math.rint(value));
+ public boolean isClamped() {
+ return true;
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return getElem(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, rint(value), strict);
+ }
+
+ private static double rint(final double rint) {
+ return (int)Math.rint(rint);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object rint(final Object rint) {
+ return rint(JSType.toNumber(rint));
+ }
+
+ @SuppressWarnings("unused")
+ private static long clampLong(final long l) {
+ if(l < 0L) {
+ return 0L;
+ } else if(l > 0xffL) {
+ return 0xffL;
+ }
+ return l;
}
}
@@ -119,7 +245,7 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
+ return (NativeUint8ClampedArray)constructorImpl(newObj, args, FACTORY);
}
NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +253,6 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint8ClampedArray";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/PrototypeObject.java b/src/jdk/nashorn/internal/objects/PrototypeObject.java
index 483f6174..b119dade 100644
--- a/src/jdk/nashorn/internal/objects/PrototypeObject.java
+++ b/src/jdk/nashorn/internal/objects/PrototypeObject.java
@@ -25,8 +25,8 @@
package jdk.nashorn.internal.objects;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
diff --git a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index dcbc7da9..f147234b 100644
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -30,6 +30,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
+import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -37,7 +38,7 @@ import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.AccessorProperty;
+import jdk.nashorn.internal.runtime.Specialization;
/**
* Concrete implementation of ScriptFunction. This sets correct map for the
@@ -58,7 +59,7 @@ public class ScriptFunctionImpl extends ScriptFunction {
// Marker object for lazily initialized prototype object
private static final Object LAZY_PROTOTYPE = new Object();
- private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) {
+ private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) {
super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -71,11 +72,11 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param invokeHandle handle for invocation
* @param specs specialized versions of this method, if available, null otherwise
*/
- ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) {
+ ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) {
this(name, invokeHandle, specs, Global.instance());
}
- private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) {
+ private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) {
super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -89,11 +90,11 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param map initial property map
* @param specs specialized versions of this method, if available, null otherwise
*/
- ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) {
+ ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) {
this(name, invokeHandle, map, specs, Global.instance());
}
- private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) {
+ private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) {
super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags);
init(global);
}
@@ -107,7 +108,7 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param specs specialized versions of this method, if available, null otherwise
* @param flags {@link ScriptFunctionData} flags
*/
- ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) {
+ ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) {
this(name, methodHandle, scope, specs, flags, Global.instance());
}
@@ -175,13 +176,22 @@ public class ScriptFunctionImpl extends ScriptFunction {
private static class AnonymousFunction extends ScriptFunctionImpl {
private static final PropertyMap anonmap$ = PropertyMap.newMap();
- AnonymousFunction(final Global global) {
+ AnonymousFunction() {
super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
}
}
- static ScriptFunctionImpl newAnonymousFunction(final Global global) {
- return new AnonymousFunction(global);
+ static ScriptFunctionImpl newAnonymousFunction() {
+ return new AnonymousFunction();
+ }
+
+ private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) {
+ final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
+ func.setPrototype(UNDEFINED);
+ // Non-constructor built-in functions do not have "prototype" property
+ func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+
+ return func;
}
/**
@@ -192,13 +202,19 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param specs specialized versions of function if available, null otherwise
* @return new ScriptFunction
*/
- static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
- final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
- func.setPrototype(UNDEFINED);
- // Non-constructor built-in functions do not have "prototype" property
- func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+ static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) {
+ return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+ }
- return func;
+ /**
+ * Factory method for non-constructor built-in, strict functions
+ *
+ * @param name function name
+ * @param methodHandle handle for invocation
+ * @return new ScriptFunction
+ */
+ static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
+ return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
}
/**
@@ -220,13 +236,13 @@ public class ScriptFunctionImpl extends ScriptFunction {
/**
* Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
- * can expose it to methods in this package.
+ * can expose it.
* @param self the self to bind to this function. Can be null (in which case, null is bound as this).
* @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
* @return a function with the specified self and parameters bound.
*/
@Override
- protected ScriptFunction makeBoundFunction(Object self, Object[] args) {
+ public ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
return super.makeBoundFunction(self, args);
}
@@ -272,14 +288,13 @@ public class ScriptFunctionImpl extends ScriptFunction {
// We have to fill user accessor functions late as these are stored
// in this object rather than in the PropertyMap of this object.
-
- final ScriptFunction errorThrower = global.getTypeErrorThrower();
+ assert objectSpill == null;
+ final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
if (findProperty("arguments", true) != null) {
- setUserAccessors("arguments", errorThrower, errorThrower);
- }
-
+ initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+ }
if (findProperty("caller", true) != null) {
- setUserAccessors("caller", errorThrower, errorThrower);
- }
+ initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+ }
}
}
diff --git a/src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java b/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
index 9e6bd0ad..09e3b2a5 100644
--- a/src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
@@ -31,17 +31,32 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * The SpecializedConstructor annotation is used to flag more type specific constructors than the standard one in
- * Native objects. For example {@link jdk.nashorn.internal.objects.NativeArray#construct} takes an arbitrary number of
- * Object elements as an array. Call this constructor, including the varargs collector that allocates the array
- * upon each invocation, is much more expensive than calling a specialized constructor that takes one arguments
- * of, e.g. int type from the call site, such as
- * {@link jdk.nashorn.internal.objects.NativeArray#construct(boolean, Object, int)}.
- * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when
- * linking the callsite.
+ * The Optimistic annotation is used for builtins that can throw UnwarrantedOptimism
+ * exception if they are wrong, whose callsite is optimistic and contains a program
+ * point. Every optimistic builtin callsite needs to bind its programPoint to an
+ * argument of the implementation at compile time
+ *
+ * Typical use case would be something like: if you want to do an optimistic "push" function
+ * in NativeArray that takes an int, write
+ *
+ * <pre>
+ * {@literal @}SpecializedFunction {@literal @}Optimistic
+ * public static int push(final Object self, final int x, final int programPoint) {
+ * try {
+ * //push code assuming that this is an int array
+ * //return new length of array, assuming it's an int
+ * } catch (ArrayWasWrong e) {
+ * //undo any array modifications
+ * throw new UnwarrantedOptimismExceptionArrayType(x, programPoint);
+ * } catch (LengthOverFlowed e) {
+ * //undo any array modifications
+ * throw new UnwarratnedOptimismExceptionArrayLength(uint32lenThatOverFlowed, programPoint)
+ * }
+ * }
+ * </pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
-public @interface SpecializedConstructor {
+public @interface Optimistic {
//empty
}
diff --git a/src/jdk/nashorn/internal/objects/annotations/Property.java b/src/jdk/nashorn/internal/objects/annotations/Property.java
index 6aec2052..7da82fe1 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Property.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Property.java
@@ -40,21 +40,25 @@ import java.lang.annotation.Target;
public @interface Property {
/**
* Name of the script property. If empty, the name is inferred.
+ * @return name
*/
public String name() default "";
/**
* Attribute flags for this function.
+ * @return attribute
*/
public int attributes() default DEFAULT_ATTRIBUTES;
/**
* Initialize this property with the object of given class.
+ * @return class
*/
public String clazz() default "";
/**
* Where this property lives?
+ * @return location of property
*/
public Where where() default Where.INSTANCE;
}
diff --git a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
index 1e75d2a7..62e6e99f 100644
--- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
+++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,18 +29,186 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.invoke.MethodHandle;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.runtime.ScriptFunction;
/**
- * The SpecializedFunction annotation is used to flag more type specific functions than the standard one in
- * Native objects. For example {@link jdk.nashorn.internal.objects.NativeMath#max} takes an arbitrary number of
- * Object elements as an array. Call this function, including the varargs collector that allocates the array
- * upon each invocation, is much more expensive than calling a specialized function that takes two arguments
- * of, e.g. int type from the call site, such as {@link jdk.nashorn.internal.objects.NativeMath#max(Object, int, int)}.
- * {@link jdk.nashorn.internal.runtime.ScriptFunction} will try to look up the most specific function when
- * linking the callsite.
+ * The SpecializedFunction annotation is used to flag more type specific
+ * functions than the standard one in the native objects
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SpecializedFunction {
- //empty
+
+ /**
+ * Functionality for testing if we are allowed to link a specialized
+ * function the first time we encounter it. Then the guard will handle the
+ * rest of the invocations
+ *
+ * This is the same for all callsites in Nashorn, the first time callsite is
+ * linked, we have to manually check that the linkage is OK. Even if we add
+ * a guard and it fails upon the first try, this is not good enough.
+ * (Symmetrical to how it works everywhere else in the Nashorn runtime).
+ *
+ * Here we abstract out a few of the most common link guard checks.
+ */
+ public static abstract class LinkLogic {
+ /**
+ * Empty link logic instance - this is the default
+ * "no special linking or runtime guard behavior"
+ */
+ public static final LinkLogic EMPTY_INSTANCE = new Empty();
+
+ /** Empty link logic class - allow all linking, no guards */
+ private static final class Empty extends LinkLogic {
+ @Override
+ public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+ }
+
+ /**
+ * Get the class representing the empty link logic
+ * @return class representing empty link logic
+ */
+ public static Class<? extends LinkLogic> getEmptyLinkLogicClass() {
+ return Empty.class;
+ }
+
+ /**
+ * Should this callsite relink when an exception is thrown
+ *
+ * @return the relink exception, or null if none
+ */
+ public Class<? extends Throwable> getRelinkException() {
+ return null;
+ }
+
+ /**
+ * Is this link logic class empty - i.e. no special linking logic
+ * supplied
+ *
+ * @param clazz class to check
+ *
+ * @return true if this link logic is empty
+ */
+ public static boolean isEmpty(final Class<? extends LinkLogic> clazz) {
+ return clazz == Empty.class;
+ }
+
+ /**
+ * Is this link logic instance empty - i.e. no special linking logic
+ * supplied
+ *
+ * @return true if this link logic instance is empty
+ */
+ public boolean isEmpty() {
+ return false;
+ }
+
+ /**
+ * Given a callsite, can we link this method based on the receiver and
+ * parameters?
+ *
+ * @param self receiver
+ * @param desc callsite descriptor
+ * @param request link request
+ *
+ * @return true if we can link this callsite at this time
+ */
+ public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request);
+
+ /**
+ * Given a callsite, do we require an extra guard for specialization to
+ * go through?
+ *
+ * @param self receiver
+ *
+ * @return true if a guard is to be woven into the callsite
+ */
+ public boolean needsGuard(final Object self) {
+ return true;
+ }
+
+ /**
+ * Given a callsite, and optional arguments, do we need an extra guard
+ * for specialization to go through - this guard can be a function of
+ * the arguments too
+ *
+ * @param self receiver
+ * @param args arguments
+ *
+ * @return true if a guard is to be woven into the callsite
+ */
+ public boolean needsGuard(final Object self, final Object... args) {
+ return true;
+ }
+
+ /**
+ * Given a callsite, and optional arguments, return any extra guard we
+ * might need for specialization as a method handle.
+ *
+ * @return methodhandle for guard, or null if no guard is needed
+ */
+ public MethodHandle getGuard() {
+ return null;
+ }
+
+ /**
+ * Check, given a link request and a receiver, if this specialization
+ * fits This is used by the linker in {@link ScriptFunction} to figure
+ * out if an optimistic builtin can be linked when first discovered
+ *
+ * @param self receiver
+ * @param desc callsite descriptor
+ * @param request link request
+
+ * @return true if we can link, false otherwise - that means we have to
+ * pick a non specialized target
+ */
+ public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
+ // check the link guard, if it says we can link, go ahead
+ return canLink(self, desc, request);
+ }
+ }
+
+ /**
+ * name override for return value polymorphism, for example we can't have
+ * pop(V)I and pop(V)D in the same Java class, so they need to be named,
+ * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their
+ * names still need to resolve to "pop" to JavaScript so we can still
+ * specialize on return values and so that the linker can find them
+ *
+ * @return name, "" means no override, use the Java function name, e.g.
+ * "push"
+ */
+ String name() default "";
+
+ /**
+ * Return the guard for this specialized function. The default is no guard.
+ *
+ * @return guard
+ */
+ Class<?> linkLogic() default LinkLogic.Empty.class;
+
+ /**
+ * Is this a specialized constructor?
+ */
+ boolean isConstructor() default false;
+
+ /**
+ * Can this function throw UnwarrantedOptimismExceptions? This works just
+ * like the normal functions, but we need the function to be
+ * immutable/non-state modifying, as we can't generate continuations for
+ * native code. Luckily a lot of the methods we want to specialize have this
+ * property
+ */
+ boolean isOptimistic() default false;
}
diff --git a/src/jdk/nashorn/internal/parser/AbstractParser.java b/src/jdk/nashorn/internal/parser/AbstractParser.java
index d4a42ba4..3eb45cfb 100644
--- a/src/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -30,7 +30,8 @@ import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
import static jdk.nashorn.internal.parser.TokenType.IDENT;
-
+import java.util.HashMap;
+import java.util.Map;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.parser.Lexer.LexerToken;
@@ -58,6 +59,9 @@ public abstract class AbstractParser {
/** Index of current token. */
protected int k;
+ /** Previous token - accessible to sub classes */
+ protected long previousToken;
+
/** Descriptor of current token. */
protected long token;
@@ -85,17 +89,20 @@ public abstract class AbstractParser {
/** Is this parser running under strict mode? */
protected boolean isStrictMode;
- /** //@ sourceURL or //# sourceURL */
- protected String sourceURL;
+ /** What should line numbers be counted from? */
+ protected final int lineOffset;
+
+ private final Map<String, String> canonicalNames = new HashMap<>();
/**
* Construct a parser.
*
- * @param source Source to parse.
- * @param errors Error reporting manager.
- * @param strict True if we are in strict mode
+ * @param source Source to parse.
+ * @param errors Error reporting manager.
+ * @param strict True if we are in strict mode
+ * @param lineOffset Offset from which lines should be counted
*/
- protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict) {
+ protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict, final int lineOffset) {
this.source = source;
this.errors = errors;
this.k = -1;
@@ -103,6 +110,7 @@ public abstract class AbstractParser {
this.type = EOL;
this.last = EOL;
this.isStrictMode = strict;
+ this.lineOffset = lineOffset;
}
/**
@@ -174,7 +182,7 @@ public abstract class AbstractParser {
// currently only @sourceURL=foo supported
private void checkDirectiveComment() {
// if already set, ignore this one
- if (sourceURL != null) {
+ if (source.getExplicitURL() != null) {
return;
}
@@ -182,7 +190,7 @@ public abstract class AbstractParser {
final int len = comment.length();
// 4 characters for directive comment marker //@\s or //#\s
if (len > 4 && comment.substring(4).startsWith(SOURCE_URL_PREFIX)) {
- sourceURL = comment.substring(4 + SOURCE_URL_PREFIX.length());
+ source.setExplicitURL(comment.substring(4 + SOURCE_URL_PREFIX.length()));
}
}
@@ -199,6 +207,7 @@ public abstract class AbstractParser {
// Set up next token.
k++;
final long lastToken = token;
+ previousToken = token;
token = getToken(k);
type = Token.descType(token);
@@ -208,7 +217,7 @@ public abstract class AbstractParser {
}
if (type == EOL) {
- line = Token.descLength(token);
+ line = Token.descLength(token);
linePosition = Token.descPosition(token);
} else {
start = Token.descPosition(token);
@@ -316,18 +325,28 @@ public abstract class AbstractParser {
}
/**
- * Check next token and advance.
+ * Check current token and advance to the next token.
*
* @param expected Expected tokenType.
*
* @throws ParserException on unexpected token type
*/
protected final void expect(final TokenType expected) throws ParserException {
+ expectDontAdvance(expected);
+ next();
+ }
+
+ /**
+ * Check current token, but don't advance to the next token.
+ *
+ * @param expected Expected tokenType.
+ *
+ * @throws ParserException on unexpected token type
+ */
+ protected final void expectDontAdvance(final TokenType expected) throws ParserException {
if (type != expected) {
throw error(expectMessage(expected));
}
-
- next();
}
/**
@@ -403,7 +422,7 @@ public abstract class AbstractParser {
next();
// Create IDENT node.
- return new IdentNode(identToken, finish, ident).setIsFutureStrictName();
+ return createIdentNode(identToken, finish, ident).setIsFutureStrictName();
}
// Get IDENT.
@@ -412,7 +431,22 @@ public abstract class AbstractParser {
return null;
}
// Create IDENT node.
- return new IdentNode(identToken, finish, ident);
+ return createIdentNode(identToken, finish, ident);
+ }
+
+ /**
+ * Creates a new {@link IdentNode} as if invoked with a {@link IdentNode#IdentNode(long, int, String)
+ * constructor} but making sure that the {@code name} is deduplicated within this parse job.
+ * @param identToken the token for the new {@code IdentNode}
+ * @param identFinish the finish for the new {@code IdentNode}
+ * @param name the name for the new {@code IdentNode}. It will be de-duplicated.
+ * @return a newly constructed {@code IdentNode} with the specified token, finish, and name; the name will
+ * be deduplicated.
+ */
+ protected IdentNode createIdentNode(final long identToken, final int identFinish, final String name) {
+ final String existingName = canonicalNames.putIfAbsent(name, name);
+ final String canonicalName = existingName != null ? existingName : name;
+ return new IdentNode(identToken, identFinish, canonicalName);
}
/**
@@ -447,7 +481,7 @@ public abstract class AbstractParser {
final String ident = (String)getValue(identToken);
next();
// Create IDENT node.
- return new IdentNode(identToken, finish, ident);
+ return createIdentNode(identToken, finish, ident);
} else {
expect(IDENT);
return null;
diff --git a/src/jdk/nashorn/internal/parser/JSONParser.java b/src/jdk/nashorn/internal/parser/JSONParser.java
index 51988f6a..7faf89a8 100644
--- a/src/jdk/nashorn/internal/parser/JSONParser.java
+++ b/src/jdk/nashorn/internal/parser/JSONParser.java
@@ -32,7 +32,6 @@ import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
import static jdk.nashorn.internal.parser.TokenType.RBRACE;
import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
import static jdk.nashorn.internal.parser.TokenType.STRING;
-
import java.util.ArrayList;
import java.util.List;
import jdk.nashorn.internal.ir.Expression;
@@ -57,7 +56,7 @@ public class JSONParser extends AbstractParser {
* @param errors the error manager
*/
public JSONParser(final Source source, final ErrorManager errors) {
- super(source, errors, false);
+ super(source, errors, false, 0);
}
/**
@@ -160,7 +159,7 @@ public class JSONParser extends AbstractParser {
}
// First digit of number.
- int digit = convertDigit(ch0, 10);
+ final int digit = convertDigit(ch0, 10);
// skip first digit
skip(1);
diff --git a/src/jdk/nashorn/internal/parser/Lexer.java b/src/jdk/nashorn/internal/parser/Lexer.java
index 653f04c0..04778cdb 100644
--- a/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/src/jdk/nashorn/internal/parser/Lexer.java
@@ -27,14 +27,15 @@ package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.ADD;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
-import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
import static jdk.nashorn.internal.parser.TokenType.ERROR;
import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
import static jdk.nashorn.internal.parser.TokenType.EXECSTRING;
import static jdk.nashorn.internal.parser.TokenType.FLOATING;
+import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
import static jdk.nashorn.internal.parser.TokenType.HEXADECIMAL;
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
import static jdk.nashorn.internal.parser.TokenType.LPAREN;
@@ -45,9 +46,11 @@ import static jdk.nashorn.internal.parser.TokenType.RPAREN;
import static jdk.nashorn.internal.parser.TokenType.STRING;
import static jdk.nashorn.internal.parser.TokenType.XML;
+import java.io.Serializable;
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;
@@ -76,7 +79,7 @@ public class Lexer extends Scanner {
private final boolean nested;
/** Pending new line number and position. */
- private int pendingLine;
+ int pendingLine;
/** Position of last EOL + 1. */
private int linePosition;
@@ -84,6 +87,9 @@ public class Lexer extends Scanner {
/** Type of last token added. */
private TokenType last;
+ private final boolean pauseOnFunctionBody;
+ private boolean pauseOnNextLeftBrace;
+
private static final String SPACETAB = " \t"; // ASCII space and tab
private static final String LFCR = "\n\r"; // line feed and carriage return (ctrl-m)
@@ -181,14 +187,32 @@ public class Lexer extends Scanner {
* @param scripting are we in scripting mode
*/
public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
- super(source.getContent(), 1, 0, source.getLength());
+ this(source, 0, source.getLength(), stream, scripting, false);
+ }
+ /**
+ * Constructor
+ *
+ * @param source the source
+ * @param start start position in source from which to start lexing
+ * @param len length of source segment to lex
+ * @param stream token stream to lex
+ * @param scripting are we in scripting mode
+ * @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
+ * function body. This is used with the feature where the parser is skipping nested function bodies to
+ * avoid reading ahead unnecessarily when we skip the function bodies.
+ */
+
+ public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
+ super(source.getContent(), 1, start, len);
this.source = source;
this.stream = stream;
this.scripting = scripting;
this.nested = false;
this.pendingLine = 1;
this.last = EOL;
+
+ this.pauseOnFunctionBody = pauseOnFunctionBody;
}
private Lexer(final Lexer lexer, final State state) {
@@ -202,6 +226,7 @@ public class Lexer extends Scanner {
pendingLine = state.pendingLine;
linePosition = state.linePosition;
last = EOL;
+ pauseOnFunctionBody = false;
}
static class State extends Scanner.State {
@@ -796,6 +821,9 @@ public class Lexer extends Scanner {
final int length = scanIdentifier();
// Check to see if it is a keyword.
final TokenType type = TokenLookup.lookupKeyword(content, start, length);
+ if (type == FUNCTION && pauseOnFunctionBody) {
+ pauseOnNextLeftBrace = true;
+ }
// Add keyword or identifier token.
add(type, start);
}
@@ -1583,6 +1611,9 @@ public class Lexer extends Scanner {
// We break to let the parser decide what it is.
if (canStartLiteral(type)) {
break;
+ } else if (type == LBRACE && pauseOnNextLeftBrace) {
+ pauseOnNextLeftBrace = false;
+ break;
}
} else if (Character.isJavaIdentifierStart(ch0) || ch0 == '\\' && ch1 == 'u') {
// Scan and add identifier or keyword.
@@ -1609,7 +1640,7 @@ public class Lexer extends Scanner {
*/
Object getValueOf(final long token, final boolean strict) {
final int start = Token.descPosition(token);
- final int len = Token.descLength(token);
+ final int len = Token.descLength(token);
switch (Token.descType(token)) {
case DECIMAL:
@@ -1619,7 +1650,23 @@ public class Lexer extends Scanner {
case HEXADECIMAL:
return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number
case FLOATING:
- return Double.valueOf(source.getString(start, len)); // number
+ final String str = source.getString(start, len);
+ final double value = Double.valueOf(str);
+ if (str.indexOf('.') != -1) {
+ return value; //number
+ }
+ //anything without an explicit decimal point is still subject to a
+ //"representable as int or long" check. Then the programmer does not
+ //explicitly code something as a double. For example new Color(int, int, int)
+ //and new Color(float, float, float) will get ambiguous for cases like
+ //new Color(1.0, 1.5, 1.5) if we don't respect the decimal point.
+ //yet we don't want e.g. 1e6 to be a double unnecessarily
+ if (JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value)) {
+ return (int)value;
+ } else if (JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value)) {
+ return (long)value;
+ }
+ return value;
case STRING:
return source.getString(start, len); // String
case ESCSTRING:
@@ -1671,7 +1718,9 @@ public class Lexer extends Scanner {
* Helper class for Lexer tokens, e.g XML or RegExp tokens.
* This is the abstract superclass
*/
- public static abstract class LexerToken {
+ public static abstract class LexerToken implements Serializable {
+ private static final long serialVersionUID = 1L;
+
private final String expression;
/**
@@ -1695,6 +1744,8 @@ public class Lexer extends Scanner {
* Temporary container for regular expressions.
*/
public static class RegexToken extends LexerToken {
+ private static final long serialVersionUID = 1L;
+
/** Options. */
private final String options;
@@ -1727,6 +1778,7 @@ public class Lexer extends Scanner {
* Temporary container for XML expression.
*/
public static class XMLToken extends LexerToken {
+ private static final long serialVersionUID = 1L;
/**
* Constructor.
diff --git a/src/jdk/nashorn/internal/parser/Parser.java b/src/jdk/nashorn/internal/parser/Parser.java
index 6ad60b58..12ad59e3 100644
--- a/src/jdk/nashorn/internal/parser/Parser.java
+++ b/src/jdk/nashorn/internal/parser/Parser.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.parser;
-import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
+import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
import static jdk.nashorn.internal.parser.TokenType.CASE;
import static jdk.nashorn.internal.parser.TokenType.CATCH;
@@ -45,6 +45,7 @@ import static jdk.nashorn.internal.parser.TokenType.IDENT;
import static jdk.nashorn.internal.parser.TokenType.IF;
import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
+import static jdk.nashorn.internal.parser.TokenType.LET;
import static jdk.nashorn.internal.parser.TokenType.LPAREN;
import static jdk.nashorn.internal.parser.TokenType.RBRACE;
import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
@@ -53,8 +54,11 @@ import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
import static jdk.nashorn.internal.parser.TokenType.TERNARY;
import static jdk.nashorn.internal.parser.TokenType.WHILE;
+import java.io.Serializable;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -84,6 +88,7 @@ import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
@@ -103,22 +108,29 @@ import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.WhileNode;
import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.ir.debug.ASTWriter;
+import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Timing;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Builds the IR.
*/
-public class Parser extends AbstractParser {
+@Logger(name="parser")
+public class Parser extends AbstractParser implements Loggable {
private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
- /** Current script environment. */
+ /** Current env. */
private final ScriptEnvironment env;
/** Is scripting mode. */
@@ -127,15 +139,18 @@ public class Parser extends AbstractParser {
private List<Statement> functionDeclarations;
private final BlockLexicalContext lc = new BlockLexicalContext();
+ private final Deque<Object> defaultNames = new ArrayDeque<>();
/** Namespace for function names where not explicitly given */
private final Namespace namespace;
- private static final DebugLogger LOG = new DebugLogger("parser");
+ private final DebugLogger log;
/** to receive line information from Lexer when scanning multine literals. */
protected final Lexer.LineInfoReceiver lineInfoReceiver;
+ private RecompilableScriptFunctionData reparsedFunction;
+
/**
* Constructor
*
@@ -144,7 +159,20 @@ public class Parser extends AbstractParser {
* @param errors error manager
*/
public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
- this(env, source, errors, env._strict);
+ this(env, source, errors, env._strict, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param env script environment
+ * @param source source to parse
+ * @param errors error manager
+ * @param strict strict
+ * @param log debug logger if one is needed
+ */
+ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
+ this(env, source, errors, strict, 0, log);
}
/**
@@ -154,10 +182,12 @@ public class Parser extends AbstractParser {
* @param source source to parse
* @param errors error manager
* @param strict parser created with strict mode enabled.
+ * @param lineOffset line offset to start counting lines from
+ * @param log debug logger if one is needed
*/
- public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) {
- super(source, errors, strict);
- this.env = env;
+ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
+ super(source, errors, strict, lineOffset);
+ this.env = env;
this.namespace = new Namespace(env.getNamespace());
this.scripting = env._scripting;
if (this.scripting) {
@@ -173,6 +203,37 @@ public class Parser extends AbstractParser {
// non-scripting mode script can't have multi-line literals
this.lineInfoReceiver = null;
}
+
+ this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ /**
+ * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
+ * preserve their already assigned name, as that name doesn't appear in their source text.
+ * @param name the name for the first parsed function.
+ */
+ public void setFunctionName(final String name) {
+ defaultNames.push(createIdentNode(0, 0, name));
+ }
+
+ /**
+ * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
+ * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
+ * This will trigger various special behaviors, such as skipping nested function bodies.
+ * @param reparsedFunction the function being reparsed.
+ */
+ public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
+ this.reparsedFunction = reparsedFunction;
}
/**
@@ -181,12 +242,12 @@ public class Parser extends AbstractParser {
* if parsing should fail
*
* This is the default parse call, which will name the function node
- * "runScript" {@link CompilerConstants#RUN_SCRIPT}
+ * {code :program} {@link CompilerConstants#PROGRAM}
*
* @return function node resulting from successful parse
*/
public FunctionNode parse() {
- return parse(RUN_SCRIPT.symbolName());
+ return parse(PROGRAM.symbolName(), 0, source.getLength(), false);
}
/**
@@ -194,35 +255,44 @@ public class Parser extends AbstractParser {
* Errors will be thrown and the error manager will contain information
* if parsing should fail
*
+ * This should be used to create one and only one function node
+ *
* @param scriptName name for the script, given to the parsed FunctionNode
+ * @param startPos start position in source
+ * @param len length of parse
+ * @param allowPropertyFunction if true, "get" and "set" are allowed as first tokens of the program, followed by
+ * a property getter or setter function. This is used when reparsing a function that can potentially be defined as a
+ * property getter or setter in an object literal.
*
* @return function node resulting from successful parse
*/
- public FunctionNode parse(final String scriptName) {
- final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
- LOG.info(this, " begin for '", scriptName, "'");
+ public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
+ final boolean isTimingEnabled = env.isTimingEnabled();
+ final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
+ log.info(this, " begin for '", scriptName, "'");
try {
stream = new TokenStream();
- lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null);
+ lexer.line = lexer.pendingLine = lineOffset + 1;
+ line = lineOffset;
// Set up first token (skips opening EOL.)
k = -1;
next();
-
// Begin parse.
- return program(scriptName);
+ return program(scriptName, allowPropertyFunction);
} catch (final Exception e) {
handleParseException(e);
return null;
} finally {
final String end = this + " end '" + scriptName + "'";
- if (Timing.isEnabled()) {
- Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
- LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms");
+ if (isTimingEnabled) {
+ env._timing.accumulateTime(toString(), System.nanoTime() - t0);
+ log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
} else {
- LOG.info(end);
+ log.info(end);
}
}
}
@@ -264,6 +334,7 @@ public class Parser extends AbstractParser {
try {
stream = new TokenStream();
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ final int functionLine = line;
// Set up first token (skips opening EOL.)
k = -1;
@@ -275,21 +346,23 @@ public class Parser extends AbstractParser {
FunctionNode function = newFunctionNode(
functionToken,
- new IdentNode(functionToken, Token.descPosition(functionToken), RUN_SCRIPT.symbolName()),
+ new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName()),
new ArrayList<IdentNode>(),
- FunctionNode.Kind.NORMAL);
+ FunctionNode.Kind.NORMAL,
+ functionLine);
functionDeclarations = new ArrayList<>();
- sourceElements();
+ sourceElements(false);
addFunctionDeclarations(function);
functionDeclarations = null;
expect(EOF);
function.setFinish(source.getLength() - 1);
-
function = restoreFunctionNode(function, token); //commit code
function = function.setBody(lc, function.getBody().setNeedsScope(lc));
+
+ printAST(function);
return function;
} catch (final Exception e) {
handleParseException(e);
@@ -381,7 +454,7 @@ loop:
* @param ident Name of function.
* @return New block.
*/
- private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
+ private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine) {
// Build function name.
final StringBuilder sb = new StringBuilder();
@@ -394,26 +467,21 @@ loop:
sb.append(ident.getName());
final String name = namespace.uniqueName(sb.toString());
- assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript().
+ assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
int flags = 0;
- if (parentFunction == null) {
- flags |= FunctionNode.IS_PROGRAM;
- }
if (isStrictMode) {
flags |= FunctionNode.IS_STRICT;
}
- if (env._specialize_calls != null) {
- if (env._specialize_calls.contains(name)) {
- flags |= FunctionNode.CAN_SPECIALIZE;
- }
+ if (parentFunction == null) {
+ flags |= FunctionNode.IS_PROGRAM;
}
// Start new block.
- FunctionNode functionNode =
+ final FunctionNode functionNode =
new FunctionNode(
source,
- line, //TODO?
+ functionLine,
token,
Token.descPosition(token),
startToken,
@@ -422,8 +490,7 @@ loop:
name,
parameters,
kind,
- flags,
- sourceURL);
+ flags);
lc.push(functionNode);
// Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
@@ -447,9 +514,8 @@ loop:
return lc.pop(functionNode).
setBody(lc, newBody).
setLastToken(lc, lastToken).
- setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED).
- snapshot(lc);
- }
+ setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED);
+ }
/**
* Get the statements in a block.
@@ -493,7 +559,7 @@ loop:
// Set up new block. Captures first token.
Block newBlock = newBlock();
try {
- statement();
+ statement(false, false, true);
} finally {
newBlock = restoreBlock(newBlock);
}
@@ -522,6 +588,10 @@ loop:
}
}
+ private boolean useBlockScope() {
+ return env._es6;
+ }
+
private static boolean isArguments(final String name) {
return ARGUMENTS_NAME.equals(name);
}
@@ -582,9 +652,13 @@ loop:
}
// Build up node.
+ if(BinaryNode.isLogical(opType)) {
+ return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
+ }
return new BinaryNode(op, lhs, rhs);
}
+
/**
* Reduce increment/decrement to simpler operations.
* @param firstToken First token.
@@ -620,19 +694,21 @@ loop:
*
* Parse the top level script.
*/
- private FunctionNode program(final String scriptName) {
- // Make a fake token for the script.
- final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
+ private FunctionNode program(final String scriptName, final boolean allowPropertyFunction) {
+ // Make a pseudo-token for the script holding its start and length.
+ final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
+ final int functionLine = line;
// Set up the script to append elements.
FunctionNode script = newFunctionNode(
functionToken,
new IdentNode(functionToken, Token.descPosition(functionToken), scriptName),
new ArrayList<IdentNode>(),
- FunctionNode.Kind.SCRIPT);
+ FunctionNode.Kind.SCRIPT,
+ functionLine);
functionDeclarations = new ArrayList<>();
- sourceElements();
+ sourceElements(allowPropertyFunction);
addFunctionDeclarations(script);
functionDeclarations = null;
@@ -642,10 +718,6 @@ loop:
script = restoreFunctionNode(script, token); //commit code
script = script.setBody(lc, script.getBody().setNeedsScope(lc));
- // user may have directive comment to set sourceURL
- if (sourceURL != null) {
- script = script.setSourceURL(lc, sourceURL);
- }
return script;
}
@@ -683,10 +755,12 @@ loop:
*
* Parse the elements of the script or function.
*/
- private void sourceElements() {
- List<Node> directiveStmts = null;
- boolean checkDirective = true;
- final boolean oldStrictMode = isStrictMode;
+ private void sourceElements(final boolean shouldAllowPropertyFunction) {
+ List<Node> directiveStmts = null;
+ boolean checkDirective = true;
+ boolean allowPropertyFunction = shouldAllowPropertyFunction;
+ final boolean oldStrictMode = isStrictMode;
+
try {
// If is a script, then process until the end of the script.
@@ -698,7 +772,8 @@ loop:
try {
// Get the next element.
- statement(true);
+ statement(true, allowPropertyFunction, false);
+ allowPropertyFunction = false;
// check for directive prologues
if (checkDirective) {
@@ -742,6 +817,12 @@ loop:
verifyStrictIdent(param, "function parameter");
}
}
+ } else if (Context.DEBUG) {
+ final int flag = FunctionNode.getDirectiveFlag(directive);
+ if (flag != 0) {
+ final FunctionNode function = lc.getCurrentFunction();
+ lc.setFlag(function, flag);
+ }
}
}
}
@@ -781,13 +862,15 @@ loop:
* Parse any of the basic statement types.
*/
private void statement() {
- statement(false);
+ statement(false, false, false);
}
/**
* @param topLevel does this statement occur at the "top level" of a script or a function?
+ * @param allowPropertyFunction allow property "get" and "set" functions?
+ * @param singleStatement are we in a single statement context?
*/
- private void statement(final boolean topLevel) {
+ private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
if (type == FUNCTION) {
// As per spec (ECMA section 12), function declarations as arbitrary statement
// is not "portable". Implementation can issue a warning or disallow the same.
@@ -800,7 +883,7 @@ loop:
block();
break;
case VAR:
- variableStatement(true);
+ variableStatement(type, true);
break;
case SEMICOLON:
emptyStatement();
@@ -850,8 +933,15 @@ loop:
expect(SEMICOLON);
break;
default:
+ if (useBlockScope() && (type == LET || type == CONST)) {
+ if (singleStatement) {
+ throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
+ }
+ variableStatement(type, true);
+ break;
+ }
if (env._const_as_var && type == CONST) {
- variableStatement(true);
+ variableStatement(TokenType.VAR, true);
break;
}
@@ -860,6 +950,20 @@ loop:
labelStatement();
return;
}
+ if(allowPropertyFunction) {
+ final String ident = (String)getValue();
+ final long propertyToken = token;
+ final int propertyLine = line;
+ if("get".equals(ident)) {
+ next();
+ addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
+ return;
+ } else if("set".equals(ident)) {
+ next();
+ addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
+ return;
+ }
+ }
}
expressionStatement();
@@ -867,6 +971,11 @@ loop:
}
}
+ private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
+ final FunctionNode fn = propertyFunction.functionNode;
+ functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
+ }
+
/**
* block :
* { StatementList? }
@@ -948,11 +1057,17 @@ loop:
* Parse a VAR statement.
* @param isStatement True if a statement (not used in a FOR.)
*/
- private List<VarNode> variableStatement(final boolean isStatement) {
+ private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
// VAR tested in caller.
next();
final List<VarNode> vars = new ArrayList<>();
+ int varFlags = 0;
+ if (varType == LET) {
+ varFlags |= VarNode.IS_LET;
+ } else if (varType == CONST) {
+ varFlags |= VarNode.IS_CONST;
+ }
while (true) {
// Get starting token.
@@ -970,11 +1085,18 @@ loop:
next();
// Get initializer expression. Suppress IN if not statement.
- init = assignmentExpression(!isStatement);
+ defaultNames.push(name);
+ try {
+ init = assignmentExpression(!isStatement);
+ } finally {
+ defaultNames.pop();
+ }
+ } else if (varType == CONST) {
+ throw error(AbstractParser.message("missing.const.assignment", name.getName()));
}
// Allocate var node.
- final VarNode var = new VarNode(varLine, varToken, finish, name, init);
+ final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags);
vars.add(var);
appendStatement(var);
@@ -986,7 +1108,7 @@ loop:
// If is a statement then handle end of line.
if (isStatement) {
- boolean semicolon = type == SEMICOLON;
+ final boolean semicolon = type == SEMICOLON;
endOfLine();
if (semicolon) {
lc.getCurrentBlock().setFinish(finish);
@@ -1088,9 +1210,12 @@ loop:
* Parse a FOR statement.
*/
private void forStatement() {
- // Create FOR node, capturing FOR token.
- ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, null, null, null, ForNode.IS_FOR);
+ // When ES6 for-let is enabled we create a container block to capture the LET.
+ final int startLine = start;
+ Block outer = useBlockScope() ? newBlock() : null;
+ // Create FOR node, capturing FOR token.
+ ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, 0);
lc.push(forNode);
try {
@@ -1110,15 +1235,23 @@ loop:
switch (type) {
case VAR:
- // Var statements captured in for outer block.
- vars = variableStatement(false);
+ // Var declaration captured in for outer block.
+ vars = variableStatement(type, false);
break;
case SEMICOLON:
break;
default:
+ if (useBlockScope() && (type == LET || type == CONST)) {
+ if (type == LET) {
+ forNode = forNode.setPerIterationScope(lc);
+ }
+ // LET/CONST declaration captured in container block created above.
+ vars = variableStatement(type, false);
+ break;
+ }
if (env._const_as_var && type == CONST) {
- // Var statements captured in for outer block.
- vars = variableStatement(false);
+ // Var declaration captured in for outer block.
+ vars = variableStatement(TokenType.VAR, false);
break;
}
@@ -1138,16 +1271,16 @@ loop:
expect(SEMICOLON);
if (type != SEMICOLON) {
- forNode = forNode.setTest(lc, expression());
+ forNode = forNode.setTest(lc, joinPredecessorExpression());
}
expect(SEMICOLON);
if (type != RPAREN) {
- forNode = forNode.setModify(lc, expression());
+ forNode = forNode.setModify(lc, joinPredecessorExpression());
}
break;
case IN:
- forNode = forNode.setIsForIn(lc);
+ forNode = forNode.setIsForIn(lc).setTest(lc, new JoinPredecessorExpression());
if (vars != null) {
// for (var i in obj)
if (vars.size() == 1) {
@@ -1180,7 +1313,7 @@ loop:
next();
// Get the collection expression.
- forNode = forNode.setModify(lc, expression());
+ forNode = forNode.setModify(lc, joinPredecessorExpression());
break;
default:
@@ -1199,7 +1332,13 @@ loop:
} finally {
lc.pop(forNode);
}
- }
+
+ if (outer != null) {
+ outer.setFinish(forNode.getFinish());
+ outer = restoreBlock(outer);
+ appendStatement(new BlockStatement(startLine, outer));
+ }
+ }
/**
* ... IterationStatement :
@@ -1240,7 +1379,7 @@ loop:
try {
expect(LPAREN);
final int whileLine = line;
- final Expression test = expression();
+ final JoinPredecessorExpression test = joinPredecessorExpression();
expect(RPAREN);
final Block body = getStatement();
appendStatement(whileNode =
@@ -1278,7 +1417,7 @@ loop:
expect(WHILE);
expect(LPAREN);
final int doLine = line;
- final Expression test = expression();
+ final JoinPredecessorExpression test = joinPredecessorExpression();
expect(RPAREN);
if (type == SEMICOLON) {
@@ -1332,8 +1471,8 @@ loop:
break;
}
- final IdentNode label = labelNode == null ? null : labelNode.getLabel();
- final LoopNode targetNode = lc.getContinueTo(label);
+ final String labelName = labelNode == null ? null : labelNode.getLabelName();
+ final LoopNode targetNode = lc.getContinueTo(labelName);
if (targetNode == null) {
throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
@@ -1342,7 +1481,7 @@ loop:
endOfLine();
// Construct and add CONTINUE node.
- appendStatement(new ContinueNode(continueLine, continueToken, finish, label == null ? null : new IdentNode(label)));
+ appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
}
/**
@@ -1382,8 +1521,8 @@ loop:
//either an explicit label - then get its node or just a "break" - get first breakable
//targetNode is what we are breaking out from.
- final IdentNode label = labelNode == null ? null : labelNode.getLabel();
- final BreakableNode targetNode = lc.getBreakable(label);
+ final String labelName = labelNode == null ? null : labelNode.getLabelName();
+ final BreakableNode targetNode = lc.getBreakable(labelName);
if (targetNode == null) {
throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
}
@@ -1391,7 +1530,7 @@ loop:
endOfLine();
// Construct and add BREAK node.
- appendStatement(new BreakNode(breakLine, breakToken, finish, label == null ? null : new IdentNode(label)));
+ appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
}
/**
@@ -1618,7 +1757,7 @@ loop:
throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
}
- LabelNode labelNode = new LabelNode(line, labelToken, finish, ident, null);
+ LabelNode labelNode = new LabelNode(line, labelToken, finish, ident.getName(), null);
try {
lc.push(labelNode);
labelNode = labelNode.setBody(lc, getStatement());
@@ -1630,7 +1769,7 @@ loop:
}
}
- /**
+ /**
* ThrowStatement :
* throw Expression ; // [no LineTerminator here]
*
@@ -1665,7 +1804,7 @@ loop:
endOfLine();
- appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, 0));
+ appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
}
/**
@@ -1730,7 +1869,7 @@ loop:
try {
// Get CATCH body.
final Block catchBody = getBlock(true);
- final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, 0);
+ final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
appendStatement(catchNode);
} finally {
catchBlock = restoreBlock(catchBlock);
@@ -1892,7 +2031,7 @@ loop:
// Skip ending of edit string expression.
expect(RBRACE);
- return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments);
+ return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
}
/**
@@ -2128,8 +2267,8 @@ loop:
private PropertyNode propertyAssignment() {
// Capture firstToken.
final long propertyToken = token;
+ final int functionLine = line;
- FunctionNode functionNode;
PropertyKey propertyName;
if (type == IDENT) {
@@ -2141,49 +2280,75 @@ loop:
switch (ident) {
case "get":
- final PropertyKey getIdent = propertyName();
- final String getterName = getIdent.getPropertyName();
- final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
- expect(LPAREN);
- expect(RPAREN);
- functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER);
- return new PropertyNode(propertyToken, finish, getIdent, null, functionNode, null);
+ final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
+ return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
case "set":
- final PropertyKey setIdent = propertyName();
- final String setterName = setIdent.getPropertyName();
- final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
- expect(LPAREN);
- // be sloppy and allow missing setter parameter even though
- // spec does not permit it!
- final IdentNode argIdent;
- if (type == IDENT || isNonStrictModeIdent()) {
- argIdent = getIdent();
- verifyStrictIdent(argIdent, "setter argument");
- } else {
- argIdent = null;
- }
- expect(RPAREN);
- List<IdentNode> parameters = new ArrayList<>();
- if (argIdent != null) {
- parameters.add(argIdent);
- }
- functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
- return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
-
+ final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
+ return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
default:
break;
}
}
- propertyName = new IdentNode(propertyToken, finish, ident).setIsPropertyName();
+ propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
} else {
propertyName = propertyName();
}
expect(COLON);
- return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
+ defaultNames.push(propertyName);
+ try {
+ return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
+ } finally {
+ defaultNames.pop();
+ }
+ }
+
+ private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
+ final PropertyKey getIdent = propertyName();
+ final String getterName = getIdent.getPropertyName();
+ final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
+ expect(LPAREN);
+ expect(RPAREN);
+ final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER, functionLine);
+
+ return new PropertyFunction(getIdent, functionNode);
+ }
+
+ private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
+ final PropertyKey setIdent = propertyName();
+ final String setterName = setIdent.getPropertyName();
+ final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
+ expect(LPAREN);
+ // be sloppy and allow missing setter parameter even though
+ // spec does not permit it!
+ final IdentNode argIdent;
+ if (type == IDENT || isNonStrictModeIdent()) {
+ argIdent = getIdent();
+ verifyStrictIdent(argIdent, "setter argument");
+ } else {
+ argIdent = null;
+ }
+ expect(RPAREN);
+ final List<IdentNode> parameters = new ArrayList<>();
+ if (argIdent != null) {
+ parameters.add(argIdent);
+ }
+ final FunctionNode functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER, functionLine);
+
+ return new PropertyFunction(setIdent, functionNode);
+ }
+
+ private static class PropertyFunction {
+ final PropertyKey ident;
+ final FunctionNode functionNode;
+
+ PropertyFunction(final PropertyKey ident, final FunctionNode function) {
+ this.ident = ident;
+ this.functionNode = function;
+ }
}
/**
@@ -2216,7 +2381,7 @@ loop:
detectSpecialFunction((IdentNode)lhs);
}
- lhs = new CallNode(callLine, callToken, finish, lhs, arguments);
+ lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
}
loop:
@@ -2231,7 +2396,7 @@ loop:
final List<Expression> arguments = optimizeList(argumentList());
// Create call node.
- lhs = new CallNode(callLine, callToken, finish, lhs, arguments);
+ lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
break;
@@ -2254,7 +2419,7 @@ loop:
final IdentNode property = getIdentifierName();
// Create property access node.
- lhs = new AccessNode(callToken, finish, lhs, property);
+ lhs = new AccessNode(callToken, finish, lhs, property.getName());
break;
@@ -2310,7 +2475,7 @@ loop:
arguments.add(objectLiteral());
}
- final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments));
+ final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
return new UnaryNode(newToken, callNode);
}
@@ -2334,7 +2499,7 @@ loop:
switch (type) {
case NEW:
- // Get new exppression.
+ // Get new expression.
lhs = newExpression();
break;
@@ -2378,7 +2543,7 @@ loop:
final IdentNode property = getIdentifierName();
// Create property access node.
- lhs = new AccessNode(callToken, finish, lhs, property);
+ lhs = new AccessNode(callToken, finish, lhs, property.getName());
break;
@@ -2429,7 +2594,7 @@ loop:
return nodeList;
}
- private static <T> List<T> optimizeList(ArrayList<T> list) {
+ private static <T> List<T> optimizeList(final ArrayList<T> list) {
switch(list.size()) {
case 0: {
return Collections.emptyList();
@@ -2479,7 +2644,7 @@ loop:
// name is null, generate anonymous name
boolean isAnonymous = false;
if (name == null) {
- final String tmpName = ANON_FUNCTION_PREFIX.symbolName() + functionLine;
+ final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
isAnonymous = true;
}
@@ -2488,10 +2653,18 @@ loop:
final List<IdentNode> parameters = formalParameterList();
expect(RPAREN);
- FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL);
+ FunctionNode functionNode;
+ // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
+ // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
+ hideDefaultName();
+ try {
+ functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
+ } finally {
+ defaultNames.pop();
+ }
if (isStatement) {
- if (topLevel) {
+ if (topLevel || useBlockScope()) {
functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
} else if (isStrictMode) {
throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
@@ -2543,9 +2716,12 @@ loop:
}
if (isStatement) {
- final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT);
+ final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
+ final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
if (topLevel) {
functionDeclarations.add(varNode);
+ } else if (useBlockScope()) {
+ prependStatement(varNode); // Hoist to beginning of current block
} else {
appendStatement(varNode);
}
@@ -2554,6 +2730,59 @@ loop:
return functionNode;
}
+ private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
+ final String defaultFunctionName = getDefaultFunctionName();
+ if (isValidIdentifier(defaultFunctionName)) {
+ if (isStatement) {
+ // The name will be used as the LHS of a symbol assignment. We add the anonymous function
+ // prefix to ensure that it can't clash with another variable.
+ return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
+ }
+ return defaultFunctionName;
+ }
+ return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
+ }
+
+ private static boolean isValidIdentifier(final String name) {
+ if(name == null || name.isEmpty()) {
+ return false;
+ }
+ if(!Character.isJavaIdentifierStart(name.charAt(0))) {
+ return false;
+ }
+ for(int i = 1; i < name.length(); ++i) {
+ if(!Character.isJavaIdentifierPart(name.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private String getDefaultFunctionName() {
+ if(!defaultNames.isEmpty()) {
+ final Object nameExpr = defaultNames.peek();
+ if(nameExpr instanceof PropertyKey) {
+ markDefaultNameUsed();
+ return ((PropertyKey)nameExpr).getPropertyName();
+ } else if(nameExpr instanceof AccessNode) {
+ markDefaultNameUsed();
+ return ((AccessNode)nameExpr).getProperty();
+ }
+ }
+ return null;
+ }
+
+ private void markDefaultNameUsed() {
+ defaultNames.pop();
+ hideDefaultName();
+ }
+
+ private void hideDefaultName() {
+ // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
+ // from. Can't be null
+ defaultNames.push("");
+ }
+
/**
* FormalParameterList :
* Identifier
@@ -2583,7 +2812,7 @@ loop:
*/
private List<IdentNode> formalParameterList(final TokenType endType) {
// Prepare to gather parameters.
- final List<IdentNode> parameters = new ArrayList<>();
+ final ArrayList<IdentNode> parameters = new ArrayList<>();
// Track commas.
boolean first = true;
@@ -2604,6 +2833,7 @@ loop:
parameters.add(ident);
}
+ parameters.trimToSize();
return parameters;
}
@@ -2616,14 +2846,18 @@ loop:
* Parse function body.
* @return function node (body.)
*/
- private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
+ private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine) {
FunctionNode functionNode = null;
long lastToken = 0L;
+ final boolean parseBody;
+ Object endParserState = null;
try {
// Create a new function block.
- functionNode = newFunctionNode(firstToken, ident, parameters, kind);
-
+ functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine);
+ assert functionNode != null;
+ final int functionId = functionNode.getId();
+ parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
// Nashorn extension: expression closures
if (!env._no_syntax_extensions && type != LBRACE) {
/*
@@ -2635,38 +2869,160 @@ loop:
// just expression as function body
final Expression expr = assignmentExpression(true);
+ lastToken = previousToken;
assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
- final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), finish, expr);
- appendStatement(returnNode);
- lastToken = token;
- functionNode.setFinish(Token.descPosition(token) + Token.descLength(token));
-
+ // EOL uses length field to store the line number
+ final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
+ // Only create the return node if we aren't skipping nested functions. Note that we aren't
+ // skipping parsing of these extended functions; they're considered to be small anyway. Also,
+ // they don't end with a single well known token, so it'd be very hard to get correctly (see
+ // the note below for reasoning on skipping happening before instead of after RBRACE for
+ // details).
+ if (parseBody) {
+ final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
+ appendStatement(returnNode);
+ }
+ functionNode.setFinish(lastFinish);
} else {
- expect(LBRACE);
+ expectDontAdvance(LBRACE);
+ if (parseBody || !skipFunctionBody(functionNode)) {
+ next();
+ // Gather the function elements.
+ final List<Statement> prevFunctionDecls = functionDeclarations;
+ functionDeclarations = new ArrayList<>();
+ try {
+ sourceElements(false);
+ addFunctionDeclarations(functionNode);
+ } finally {
+ functionDeclarations = prevFunctionDecls;
+ }
- // Gather the function elements.
- final List<Statement> prevFunctionDecls = functionDeclarations;
- functionDeclarations = new ArrayList<>();
- try {
- sourceElements();
- addFunctionDeclarations(functionNode);
- } finally {
- functionDeclarations = prevFunctionDecls;
+ lastToken = token;
+ if (parseBody) {
+ // Since the lexer can read ahead and lexify some number of tokens in advance and have
+ // them buffered in the TokenStream, we need to produce a lexer state as it was just
+ // before it lexified RBRACE, and not whatever is its current (quite possibly well read
+ // ahead) state.
+ endParserState = new ParserState(Token.descPosition(token), line, linePosition);
+
+ // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
+ // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
+ // state after it. The reason is that RBRACE is a well-known token that we can expect and
+ // will never involve us getting into a weird lexer state, and as such is a great reparse
+ // point. Typical example of a weird lexer state after RBRACE would be:
+ // function this_is_skipped() { ... } "use strict";
+ // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
+ // of compensating for the possibility of a string literal (or similar) after RBRACE,
+ // we'll rather just restart parsing from this well-known, friendly token instead.
+ }
}
-
- lastToken = token;
expect(RBRACE);
functionNode.setFinish(finish);
-
}
} finally {
functionNode = restoreFunctionNode(functionNode, lastToken);
}
+
+ // NOTE: we can only do alterations to the function node after restoreFunctionNode.
+
+ if (parseBody) {
+ functionNode = functionNode.setEndParserState(lc, endParserState);
+ } else if (functionNode.getBody().getStatementCount() > 0){
+ // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
+ // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
+ // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
+ // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
+ // nested bodies early if we were supposed to skip 'em.
+ functionNode = functionNode.setBody(null, functionNode.getBody().setStatements(null,
+ Collections.<Statement>emptyList()));
+ }
+
+ if (reparsedFunction != null) {
+ // We restore the flags stored in the function's ScriptFunctionData that we got when we first
+ // eagerly parsed the code. We're doing it because some flags would be set based on the
+ // content of the function, or even content of its nested functions, most of which are normally
+ // skipped during an on-demand compilation.
+ final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+ if (data != null) {
+ // Data can be null if when we originally parsed the file, we removed the function declaration
+ // as it was dead code.
+ functionNode = functionNode.setFlags(lc, data.getFunctionFlags());
+ // This compensates for missing markEval() in case the function contains an inner function
+ // that contains eval(), that now we didn't discover since we skipped the inner function.
+ if (functionNode.hasNestedEval()) {
+ assert functionNode.hasScopeBlock();
+ functionNode = functionNode.setBody(lc, functionNode.getBody().setNeedsScope(null));
+ }
+ }
+ }
+ printAST(functionNode);
return functionNode;
}
+ private boolean skipFunctionBody(final FunctionNode functionNode) {
+ if (reparsedFunction == null) {
+ // Not reparsing, so don't skip any function body.
+ return false;
+ }
+ // Skip to the RBRACE of this function, and continue parsing from there.
+ final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
+ if (data == null) {
+ // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
+ // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
+ // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
+ return false;
+ }
+ final ParserState parserState = (ParserState)data.getEndParserState();
+ assert parserState != null;
+
+ stream.reset();
+ lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
+ line = parserState.line;
+ linePosition = parserState.linePosition;
+ // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
+ // the RBRACE.
+ type = SEMICOLON;
+ k = -1;
+ next();
+
+ return true;
+ }
+
+ /**
+ * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
+ * for resuming parsing after skipping a function body.
+ */
+ private static class ParserState implements Serializable {
+ private final int position;
+ private final int line;
+ private final int linePosition;
+
+ private static final long serialVersionUID = -2382565130754093694L;
+
+ ParserState(final int position, final int line, final int linePosition) {
+ this.position = position;
+ this.line = line;
+ this.linePosition = linePosition;
+ }
+
+ Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
+ final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
+ newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
+ return newLexer;
+ }
+ }
+
+ private void printAST(final FunctionNode functionNode) {
+ if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+ env.getErr().println(new ASTWriter(functionNode));
+ }
+
+ if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+ env.getErr().println(new PrintVisitor(functionNode, true, false));
+ }
+ }
+
private void addFunctionDeclarations(final FunctionNode functionNode) {
- assert lc.peek() == lc.getFunctionBody(functionNode);
VarNode lastDecl = null;
for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
Statement decl = functionDeclarations.get(i);
@@ -2919,6 +3275,10 @@ loop:
return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
}
+ private JoinPredecessorExpression joinPredecessorExpression() {
+ return new JoinPredecessorExpression(expression());
+ }
+
private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
// Get the precedence of the next operator.
int precedence = type.getPrecedence();
@@ -2935,33 +3295,42 @@ loop:
// Pass expression. Middle expression of a conditional expression can be a "in"
// expression - even in the contexts where "in" is not permitted.
- final Expression rhs = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
+ final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
expect(COLON);
// Fail expression.
- final Expression third = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
+ final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
// Build up node.
- lhs = new TernaryNode(op, lhs, rhs, third);
+ lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
} else {
// Skip operator.
next();
// Get the next primary expression.
- Expression rhs = unaryExpression();
-
- // Get precedence of next operator.
- int nextPrecedence = type.getPrecedence();
-
- // Subtask greater precedence.
- while (type.isOperator(noIn) &&
- (nextPrecedence > precedence ||
- nextPrecedence == precedence && !type.isLeftAssociative())) {
- rhs = expression(rhs, nextPrecedence, noIn);
- nextPrecedence = type.getPrecedence();
+ Expression rhs;
+ final boolean isAssign = Token.descType(op) == ASSIGN;
+ if(isAssign) {
+ defaultNames.push(lhs);
+ }
+ try {
+ rhs = unaryExpression();
+ // Get precedence of next operator.
+ int nextPrecedence = type.getPrecedence();
+
+ // Subtask greater precedence.
+ while (type.isOperator(noIn) &&
+ (nextPrecedence > precedence ||
+ nextPrecedence == precedence && !type.isLeftAssociative())) {
+ rhs = expression(rhs, nextPrecedence, noIn);
+ nextPrecedence = type.getPrecedence();
+ }
+ } finally {
+ if(isAssign) {
+ defaultNames.pop();
+ }
}
-
lhs = verifyAssignment(op, lhs, rhs);
}
@@ -3001,7 +3370,7 @@ loop:
@Override
public String toString() {
- return "[JavaScript Parsing]";
+ return "'JavaScript Parsing'";
}
private static void markEval(final LexicalContext lc) {
@@ -3015,6 +3384,9 @@ loop:
} else {
lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL);
}
+ // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
+ // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
+ // this method when the parser skips a nested function.
lc.setBlockNeedsScope(lc.getFunctionBody(fn));
}
}
diff --git a/src/jdk/nashorn/internal/parser/Token.java b/src/jdk/nashorn/internal/parser/Token.java
index 0012daa6..43df83b0 100644
--- a/src/jdk/nashorn/internal/parser/Token.java
+++ b/src/jdk/nashorn/internal/parser/Token.java
@@ -61,6 +61,28 @@ public class Token {
}
/**
+ * Normally returns the token itself, except in case of string tokens
+ * which report their position past their opening delimiter and thus
+ * need to have position and length adjusted.
+ *
+ * @param token Token descriptor.
+ * @return same or adjusted token.
+ */
+ public static long withDelimiter(final long token) {
+ final TokenType tokenType = Token.descType(token);
+ switch(tokenType) {
+ case STRING: case ESCSTRING: case EXECSTRING: {
+ final int start = Token.descPosition(token) - 1;
+ final int len = Token.descLength(token) + 2;
+ return toDesc(tokenType, start, len);
+ }
+ default: {
+ return token;
+ }
+ }
+ }
+
+ /**
* Extract token length from a token descriptor.
* @param token Token descriptor.
* @return Length of the token.
diff --git a/src/jdk/nashorn/internal/parser/TokenStream.java b/src/jdk/nashorn/internal/parser/TokenStream.java
index ee81ce39..f7df999f 100644
--- a/src/jdk/nashorn/internal/parser/TokenStream.java
+++ b/src/jdk/nashorn/internal/parser/TokenStream.java
@@ -209,4 +209,8 @@ public class TokenStream {
in = count;
buffer = newBuffer;
}
+
+ void reset() {
+ in = out = count = base = 0;
+ }
}
diff --git a/src/jdk/nashorn/internal/parser/TokenType.java b/src/jdk/nashorn/internal/parser/TokenType.java
index 59005077..36d1ecd1 100644
--- a/src/jdk/nashorn/internal/parser/TokenType.java
+++ b/src/jdk/nashorn/internal/parser/TokenType.java
@@ -25,7 +25,6 @@
package jdk.nashorn.internal.parser;
-import java.util.Locale;
import static jdk.nashorn.internal.parser.TokenKind.BINARY;
import static jdk.nashorn.internal.parser.TokenKind.BRACKET;
import static jdk.nashorn.internal.parser.TokenKind.FUTURE;
@@ -36,6 +35,8 @@ import static jdk.nashorn.internal.parser.TokenKind.LITERAL;
import static jdk.nashorn.internal.parser.TokenKind.SPECIAL;
import static jdk.nashorn.internal.parser.TokenKind.UNARY;
+import java.util.Locale;
+
/**
* Description of all the JavaScript tokens.
*/
@@ -182,7 +183,6 @@ public enum TokenType {
ARRAY (LITERAL, null),
COMMALEFT (IR, null),
- DISCARD (IR, null),
DECPOSTFIX (IR, null),
INCPOSTFIX (IR, null);
diff --git a/src/jdk/nashorn/internal/runtime/AccessorProperty.java b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
index e8ff153d..a9afeb93 100644
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
@@ -25,38 +25,38 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.ACCESSOR_TYPES;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.LOG;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_TYPE;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGuardBoxedPrimitiveSetter;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorType;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorTypeIndex;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getNumberOfAccessorTypes;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldCount;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
-
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.io.IOException;
import java.io.ObjectInputStream;
-import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import java.util.function.Supplier;
+import java.util.logging.Level;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.objects.Global;
/**
* An AccessorProperty is the most generic property type. An AccessorProperty is
* represented as fields in a ScriptObject class.
*/
-public final class AccessorProperty extends Property implements Serializable {
- private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
- private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class);
+public class AccessorProperty extends Property {
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ private static final MethodHandle REPLACE_MAP = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class);
+ private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, AccessorProperty.class, Object.class);
private static final int NOOF_TYPES = getNumberOfAccessorTypes();
private static final long serialVersionUID = 3371720170182154920L;
@@ -67,51 +67,58 @@ public final class AccessorProperty extends Property implements Serializable {
* these are the most frequently retrieved ones, and lookup of method handle natives only registers in the profiler
* for them.
*/
- private static ClassValue<GettersSetters> GETTERS_SETTERS = new ClassValue<GettersSetters>() {
+ private static ClassValue<Accessors> GETTERS_SETTERS = new ClassValue<Accessors>() {
@Override
- protected GettersSetters computeValue(Class<?> structure) {
- return new GettersSetters(structure);
+ protected Accessors computeValue(final Class<?> structure) {
+ return new Accessors(structure);
}
};
- /** Property getter cache */
- private transient MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
-
- private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
- private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
- private static final MethodType ACCESSOR_GETTER_PRIMITIVE_TYPE;
- private static final MethodType ACCESSOR_SETTER_PRIMITIVE_TYPE;
- private static final MethodHandle SPILL_ELEMENT_GETTER;
- private static final MethodHandle SPILL_ELEMENT_SETTER;
+ private static class Accessors {
+ final MethodHandle[] objectGetters;
+ final MethodHandle[] objectSetters;
+ final MethodHandle[] primitiveGetters;
+ final MethodHandle[] primitiveSetters;
- private static final int SPILL_CACHE_SIZE = 8;
- private static final MethodHandle[] SPILL_ACCESSORS = new MethodHandle[SPILL_CACHE_SIZE * 2];
-
- static {
- MethodType getterPrimitiveType = null;
- MethodType setterPrimitiveType = null;
-
- for (int i = 0; i < NOOF_TYPES; i++) {
- final Type type = ACCESSOR_TYPES.get(i);
- ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class);
- ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass());
+ /**
+ * Normal
+ * @param structure
+ */
+ Accessors(final Class<?> structure) {
+ final int fieldCount = getFieldCount(structure);
+ objectGetters = new MethodHandle[fieldCount];
+ objectSetters = new MethodHandle[fieldCount];
+ primitiveGetters = new MethodHandle[fieldCount];
+ primitiveSetters = new MethodHandle[fieldCount];
+
+ for (int i = 0; i < fieldCount; i++) {
+ final String fieldName = getFieldName(i, Type.OBJECT);
+ final Class<?> typeClass = Type.OBJECT.getTypeClass();
+ objectGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldName, typeClass), Lookup.GET_OBJECT_TYPE);
+ objectSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldName, typeClass), Lookup.SET_OBJECT_TYPE);
+ }
- if (type == PRIMITIVE_TYPE) {
- getterPrimitiveType = ACCESSOR_GETTER_TYPES[i];
- setterPrimitiveType = ACCESSOR_SETTER_TYPES[i];
+ if (!OBJECT_FIELDS_ONLY) {
+ for (int i = 0; i < fieldCount; i++) {
+ final String fieldNamePrimitive = getFieldName(i, PRIMITIVE_FIELD_TYPE);
+ final Class<?> typeClass = PRIMITIVE_FIELD_TYPE.getTypeClass();
+ primitiveGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.GET_PRIMITIVE_TYPE);
+ primitiveSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.SET_PRIMITIVE_TYPE);
+ }
}
}
-
- ACCESSOR_GETTER_PRIMITIVE_TYPE = getterPrimitiveType;
- ACCESSOR_SETTER_PRIMITIVE_TYPE = setterPrimitiveType;
-
- final MethodType spillGetterType = MethodType.methodType(Object[].class, Object.class);
- final MethodHandle spillGetter = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), spillGetterType);
- SPILL_ELEMENT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, spillGetter);
- SPILL_ELEMENT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, spillGetter);
}
/**
+ * Property getter cache
+ * Note that we can't do the same simple caching for optimistic getters,
+ * due to the fact that they are bound to a program point, which will
+ * produce different boun method handles wrapping the same access mechanism
+ * depending on callsite
+ */
+ private transient MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES];
+
+ /**
* Create a new accessor property. Factory method used by nasgen generated code.
*
* @param key {@link Property} key.
@@ -126,23 +133,16 @@ public final class AccessorProperty extends Property implements Serializable {
}
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
- private transient MethodHandle primitiveGetter;
+ transient MethodHandle primitiveGetter;
/** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
- private transient MethodHandle primitiveSetter;
+ transient MethodHandle primitiveSetter;
/** Seed getter for the Object version of this field */
- private transient MethodHandle objectGetter;
+ transient MethodHandle objectGetter;
/** Seed setter for the Object version of this field */
- private transient MethodHandle objectSetter;
-
- /**
- * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
- * null means undefined, and primitive types are allowed. The reason a special type is used for
- * undefined, is that are no bits left to represent it in primitive types
- */
- private Class<?> currentType;
+ transient MethodHandle objectSetter;
/**
* Delegate constructor for bound properties. This is used for properties created by
@@ -156,33 +156,50 @@ public final class AccessorProperty extends Property implements Serializable {
* @param delegate delegate object to rebind receiver to
*/
AccessorProperty(final AccessorProperty property, final Object delegate) {
- super(property);
+ super(property, property.getFlags() | IS_BOUND);
this.primitiveGetter = bindTo(property.primitiveGetter, delegate);
this.primitiveSetter = bindTo(property.primitiveSetter, delegate);
- this.objectGetter = bindTo(property.ensureObjectGetter(), delegate);
- this.objectSetter = bindTo(property.ensureObjectSetter(), delegate);
-
+ this.objectGetter = bindTo(property.objectGetter, delegate);
+ this.objectSetter = bindTo(property.objectSetter, delegate);
+ property.GETTER_CACHE = new MethodHandle[NOOF_TYPES];
// Properties created this way are bound to a delegate
- this.flags |= IS_BOUND;
- setCurrentType(property.getCurrentType());
+ setType(property.getType());
}
/**
+ * SPILL PROPERTY or USER ACCESSOR PROPERTY abstract constructor
+ *
* Constructor for spill properties. Array getters and setters will be created on demand.
*
* @param key the property key
* @param flags the property flags
* @param slot spill slot
+ * @param primitiveGetter primitive getter
+ * @param primitiveSetter primitive setter
+ * @param objectGetter object getter
+ * @param objectSetter object setter
*/
- public AccessorProperty(final String key, final int flags, final int slot) {
+ protected AccessorProperty(
+ final String key,
+ final int flags,
+ final int slot,
+ final MethodHandle primitiveGetter,
+ final MethodHandle primitiveSetter,
+ final MethodHandle objectGetter,
+ final MethodHandle objectSetter) {
super(key, flags, slot);
- assert (flags & IS_SPILL) == IS_SPILL;
-
- setCurrentType(Object.class);
+ assert getClass() != AccessorProperty.class;
+ this.primitiveGetter = primitiveGetter;
+ this.primitiveSetter = primitiveSetter;
+ this.objectGetter = objectGetter;
+ this.objectSetter = objectSetter;
+ initializeType();
}
/**
+ * NASGEN constructor
+ *
* Constructor. Similar to the constructor with both primitive getters and setters, the difference
* here being that only one getter and setter (setter is optional for non writable fields) is given
* to the constructor, and the rest are created from those. Used e.g. by Nasgen classes
@@ -193,8 +210,9 @@ public final class AccessorProperty extends Property implements Serializable {
* @param getter the property getter
* @param setter the property setter or null if non writable, non configurable
*/
- AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
- super(key, flags, slot);
+ private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
+ super(key, flags | IS_BUILTIN | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot);
+ assert !isSpill();
// we don't need to prep the setters these will never be invalidated as this is a nasgen
// or known type getter/setter. No invalidations will take place
@@ -203,40 +221,31 @@ public final class AccessorProperty extends Property implements Serializable {
final Class<?> setterType = setter == null ? null : setter.type().parameterType(1);
assert setterType == null || setterType == getterType;
-
- if (getterType.isPrimitive()) {
- for (int i = 0; i < NOOF_TYPES; i++) {
- getters[i] = MH.asType(
- Lookup.filterReturnType(
- getter,
- getAccessorType(i).getTypeClass()),
- ACCESSOR_GETTER_TYPES[i]);
- }
+ if (OBJECT_FIELDS_ONLY) {
+ primitiveGetter = primitiveSetter = null;
} else {
- objectGetter = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
- objectSetter = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
+ if (getterType == int.class || getterType == long.class) {
+ primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE);
+ primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE);
+ } else if (getterType == double.class) {
+ primitiveGetter = MH.asType(MH.filterReturnValue(getter, ObjectClassGenerator.PACK_DOUBLE), Lookup.GET_PRIMITIVE_TYPE);
+ primitiveSetter = setter == null ? null : MH.asType(MH.filterArguments(setter, 1, ObjectClassGenerator.UNPACK_DOUBLE), Lookup.SET_PRIMITIVE_TYPE);
+ } else {
+ primitiveGetter = primitiveSetter = null;
+ }
}
- setCurrentType(getterType);
- }
+ assert primitiveGetter == null || primitiveGetter.type() == Lookup.GET_PRIMITIVE_TYPE : primitiveGetter + "!=" + Lookup.GET_PRIMITIVE_TYPE;
+ assert primitiveSetter == null || primitiveSetter.type() == Lookup.SET_PRIMITIVE_TYPE : primitiveSetter;
- private static class GettersSetters {
- final MethodHandle[] getters;
- final MethodHandle[] setters;
+ objectGetter = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
+ objectSetter = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
- public GettersSetters(Class<?> structure) {
- final int fieldCount = ObjectClassGenerator.getFieldCount(structure);
- getters = new MethodHandle[fieldCount];
- setters = new MethodHandle[fieldCount];
- for(int i = 0; i < fieldCount; ++i) {
- final String fieldName = ObjectClassGenerator.getFieldName(i, Type.OBJECT);
- getters[i] = MH.asType(MH.getter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.GET_OBJECT_TYPE);
- setters[i] = MH.asType(MH.setter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.SET_OBJECT_TYPE);
- }
- }
+ setType(OBJECT_FIELDS_ONLY ? Object.class : getterType);
}
/**
+ * Normal ACCESS PROPERTY constructor given a structure class.
* Constructor for dual field AccessorPropertys.
*
* @param key property key
@@ -248,77 +257,119 @@ public final class AccessorProperty extends Property implements Serializable {
super(key, flags, slot);
initGetterSetter(structure);
+ initializeType();
}
private void initGetterSetter(final Class<?> structure) {
final int slot = getSlot();
- final String key = getKey();
/*
* primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
* works in dual field mode, it only means that the property never has a primitive
* representation.
*/
- primitiveGetter = null;
- primitiveSetter = null;
if (isParameter() && hasArguments()) {
- final MethodHandle arguments = MH.getter(lookup, structure, "arguments", ScriptObject.class);
-
+ //parameters are always stored in an object array, which may or may not be a good idea
+ final MethodHandle arguments = MH.getter(LOOKUP, structure, "arguments", ScriptObject.class);
objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.GET_OBJECT_TYPE);
objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.SET_OBJECT_TYPE);
+ primitiveGetter = null;
+ primitiveSetter = null;
} else {
- final GettersSetters gs = GETTERS_SETTERS.get(structure);
- objectGetter = gs.getters[slot];
- objectSetter = gs.setters[slot];
-
- if (!OBJECT_FIELDS_ONLY) {
- final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, PRIMITIVE_TYPE);
- final Class<?> typeClass = PRIMITIVE_TYPE.getTypeClass();
- primitiveGetter = MH.asType(MH.getter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_GETTER_PRIMITIVE_TYPE);
- primitiveSetter = MH.asType(MH.setter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_SETTER_PRIMITIVE_TYPE);
- }
+ final Accessors gs = GETTERS_SETTERS.get(structure);
+ objectGetter = gs.objectGetters[slot];
+ primitiveGetter = gs.primitiveGetters[slot];
+ objectSetter = gs.objectSetters[slot];
+ primitiveSetter = gs.primitiveSetters[slot];
}
+ }
- Class<?> initialType = null;
-
- if (OBJECT_FIELDS_ONLY || isAlwaysObject()) {
- initialType = Object.class;
- } else if (!canBePrimitive()) {
- info(key + " cannot be primitive");
- initialType = Object.class;
- } else {
- info(key + " CAN be primitive");
- if (!canBeUndefined()) {
- info(key + " is always defined");
- initialType = int.class; //double works too for less type invalidation, but this requires experimentation, e.g. var x = 17; x += 2 will turn it into double now because of lack of range analysis
- }
- }
+ /**
+ * Constructor
+ *
+ * @param key key
+ * @param flags flags
+ * @param slot field slot index
+ * @param owner owner of property
+ * @param initialValue initial value to which the property can be set
+ */
+ protected AccessorProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
+ this(key, flags, owner.getClass(), slot);
+ setInitialValue(owner, initialValue);
+ }
- // is always object means "is never initialized to undefined, and always of object type
- setCurrentType(initialType);
+ /**
+ * Normal access property constructor that overrides the type
+ * Override the initial type. Used for Object Literals
+ *
+ * @param key key
+ * @param flags flags
+ * @param structure structure to JO subclass
+ * @param slot field slot index
+ * @param initialType initial type of the property
+ */
+ public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) {
+ this(key, flags, structure, slot);
+ setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
}
/**
- * Copy constructor
+ * Copy constructor that may change type and in that case clear the cache. Important to do that before
+ * type change or getters will be created already stale.
*
- * @param property source property
+ * @param property property
+ * @param newType new type
*/
- protected AccessorProperty(final AccessorProperty property) {
- super(property);
+ protected AccessorProperty(final AccessorProperty property, final Class<?> newType) {
+ super(property, property.getFlags());
- this.getters = property.getters;
+ this.GETTER_CACHE = newType != property.getLocalType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE;
this.primitiveGetter = property.primitiveGetter;
this.primitiveSetter = property.primitiveSetter;
this.objectGetter = property.objectGetter;
this.objectSetter = property.objectSetter;
- setCurrentType(property.getCurrentType());
+ setType(newType);
+ }
+
+ /**
+ * COPY constructor
+ *
+ * @param property source property
+ */
+ protected AccessorProperty(final AccessorProperty property) {
+ this(property, property.getLocalType());
+ }
+
+ /**
+ * Set initial value of a script object's property
+ * @param owner owner
+ * @param initialValue initial value
+ */
+ protected final void setInitialValue(final ScriptObject owner, final Object initialValue) {
+ setType(JSType.unboxedFieldType(initialValue));
+ if (initialValue instanceof Integer) {
+ invokeSetter(owner, ((Integer)initialValue).intValue());
+ } else if (initialValue instanceof Long) {
+ invokeSetter(owner, ((Long)initialValue).longValue());
+ } else if (initialValue instanceof Double) {
+ invokeSetter(owner, ((Double)initialValue).doubleValue());
+ } else {
+ invokeSetter(owner, initialValue);
+ }
+ }
+
+ /**
+ * Initialize the type of a property
+ */
+ protected final void initializeType() {
+ setType(OBJECT_FIELDS_ONLY ? Object.class : null);
}
private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
// Restore getters array
- getters = new MethodHandle[NOOF_TYPES];
+ GETTER_CACHE = new MethodHandle[NOOF_TYPES];
}
private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) {
@@ -330,83 +381,217 @@ public final class AccessorProperty extends Property implements Serializable {
}
@Override
- protected Property copy() {
+ public Property copy() {
return new AccessorProperty(this);
}
@Override
- public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
- if (isSpill()) {
- self.spill[getSlot()] = value;
- } else {
- try {
- getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
- } catch (final Error|RuntimeException e) {
- throw e;
- } catch (final Throwable e) {
- throw new RuntimeException(e);
- }
- }
+ public Property copy(final Class<?> newType) {
+ return new AccessorProperty(this, newType);
}
@Override
- public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
- if (isSpill()) {
- return self.spill[getSlot()];
+ public int getIntValue(final ScriptObject self, final ScriptObject owner) {
+ try {
+ return (int)getGetter(int.class).invokeExact((Object)self);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public long getLongValue(final ScriptObject self, final ScriptObject owner) {
+ try {
+ return (long)getGetter(long.class).invokeExact((Object)self);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
}
+ }
+ @Override
+ public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
+ try {
+ return (double)getGetter(double.class).invokeExact((Object)self);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
try {
return getGetter(Object.class).invokeExact((Object)self);
- } catch (final Error|RuntimeException e) {
+ } catch (final Error | RuntimeException e) {
throw e;
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
- // Spill getters and setters are lazily initialized, see JDK-8011630
- private MethodHandle ensureObjectGetter() {
- if (isSpill() && objectGetter == null) {
- objectGetter = getSpillGetter();
+ /**
+ * Invoke setter for this property with a value
+ * @param self owner
+ * @param value value
+ */
+ protected final void invokeSetter(final ScriptObject self, final int value) {
+ try {
+ getSetter(int.class, self.getMap()).invokeExact((Object)self, value);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Invoke setter for this property with a value
+ * @param self owner
+ * @param value value
+ */
+ protected final void invokeSetter(final ScriptObject self, final long value) {
+ try {
+ getSetter(long.class, self.getMap()).invokeExact((Object)self, value);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Invoke setter for this property with a value
+ * @param self owner
+ * @param value value
+ */
+ protected final void invokeSetter(final ScriptObject self, final double value) {
+ try {
+ getSetter(double.class, self.getMap()).invokeExact((Object)self, value);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
}
- return objectGetter;
}
- private MethodHandle ensureObjectSetter() {
- if (isSpill() && objectSetter == null) {
- objectSetter = getSpillSetter();
+ /**
+ * Invoke setter for this property with a value
+ * @param self owner
+ * @param value value
+ */
+ protected final void invokeSetter(final ScriptObject self, final Object value) {
+ try {
+ getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
+ } catch (final Error | RuntimeException e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
}
- return objectSetter;
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict) {
+ assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+ invokeSetter(self, value);
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) {
+ assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+ invokeSetter(self, value);
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) {
+ assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+ invokeSetter(self, value);
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
+ //this is sometimes used for bootstrapping, hence no assert. ugly.
+ invokeSetter(self, value);
}
@Override
void initMethodHandles(final Class<?> structure) {
+ // sanity check for structure class
if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) {
throw new IllegalArgumentException();
}
- if (!isSpill()) {
- initGetterSetter(structure);
- }
+ // this method is overridden in SpillProperty
+ assert !isSpill();
+ initGetterSetter(structure);
}
@Override
public MethodHandle getGetter(final Class<?> type) {
final int i = getAccessorTypeIndex(type);
- ensureObjectGetter();
- if (getters[i] == null) {
- getters[i] = debug(
- createGetter(currentType, type, primitiveGetter, objectGetter),
- currentType, type, "get");
+ assert type == int.class ||
+ type == long.class ||
+ type == double.class ||
+ type == Object.class :
+ "invalid getter type " + type + " for " + getKey();
+
+ checkUndeclared();
+
+ //all this does is add a return value filter for object fields only
+ final MethodHandle[] getterCache = GETTER_CACHE;
+ final MethodHandle cachedGetter = getterCache[i];
+ final MethodHandle getter;
+ if (cachedGetter != null) {
+ getter = cachedGetter;
+ } else {
+ getter = debug(
+ createGetter(
+ getLocalType(),
+ type,
+ primitiveGetter,
+ objectGetter,
+ INVALID_PROGRAM_POINT),
+ getLocalType(),
+ type,
+ "get");
+ getterCache[i] = getter;
+ }
+ assert getter.type().returnType() == type && getter.type().parameterType(0) == Object.class;
+ return getter;
+ }
+
+ @Override
+ public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
+ // nasgen generated primitive fields like Math.PI have only one known unchangeable primitive type
+ if (objectGetter == null) {
+ return getOptimisticPrimitiveGetter(type, programPoint);
}
- return getters[i];
+ checkUndeclared();
+
+ return debug(
+ createGetter(
+ getLocalType(),
+ type,
+ primitiveGetter,
+ objectGetter,
+ programPoint),
+ getLocalType(),
+ type,
+ "get");
+ }
+
+ private MethodHandle getOptimisticPrimitiveGetter(final Class<?> type, final int programPoint) {
+ final MethodHandle g = getGetter(getLocalType());
+ return MH.asType(OptimisticReturnFilters.filterOptimisticReturnValue(g, type, programPoint), g.type().changeReturnType(type));
}
private Property getWiderProperty(final Class<?> type) {
- final AccessorProperty newProperty = new AccessorProperty(this);
- newProperty.invalidate(type);
- return newProperty;
+ return copy(type); //invalidate cache of new property
}
private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) {
@@ -416,126 +601,161 @@ public final class AccessorProperty extends Property implements Serializable {
return newMap;
}
+ private void checkUndeclared() {
+ if ((getFlags() & NEEDS_DECLARATION) != 0) {
+ // a lexically defined variable that hasn't seen its declaration - throw ReferenceError
+ throw ECMAErrors.referenceError("not.defined", getKey());
+ }
+ }
+
// the final three arguments are for debug printout purposes only
@SuppressWarnings("unused")
- private static Object replaceMap(final Object sobj, final PropertyMap newMap, final String key, final Class<?> oldType, final Class<?> newType) {
- if (DEBUG_FIELDS) {
- final PropertyMap oldMap = ((ScriptObject)sobj).getMap();
- info("Type change for '" + key + "' " + oldType + "=>" + newType);
- finest("setting map " + sobj + " from " + Debug.id(oldMap) + " to " + Debug.id(newMap) + " " + oldMap + " => " + newMap);
- }
+ private static Object replaceMap(final Object sobj, final PropertyMap newMap) {
((ScriptObject)sobj).setMap(newMap);
return sobj;
}
+ @SuppressWarnings("unused")
+ private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) {
+ if (!property.builtinSwitchPoint.hasBeenInvalidated()) {
+ SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint });
+ }
+ return obj;
+ }
+
private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
- ensureObjectSetter();
- MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter);
- mh = debug(mh, currentType, type, "set");
- return mh;
+ return debug(createSetter(forType, type, primitiveSetter, objectSetter), getLocalType(), type, "set");
+ }
+
+ /**
+ * Is this property of the undefined type?
+ * @return true if undefined
+ */
+ protected final boolean isUndefined() {
+ return getLocalType() == null;
}
@Override
public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
- final int i = getAccessorTypeIndex(type);
- final int ci = currentType == null ? -1 : getAccessorTypeIndex(currentType);
- final Class<?> forType = currentType == null ? type : currentType;
+ checkUndeclared();
+
+ final int typeIndex = getAccessorTypeIndex(type);
+ final int currentTypeIndex = getAccessorTypeIndex(getLocalType());
//if we are asking for an object setter, but are still a primitive type, we might try to box it
MethodHandle mh;
-
- if (needsInvalidator(i, ci)) {
+ if (needsInvalidator(typeIndex, currentTypeIndex)) {
final Property newProperty = getWiderProperty(type);
final PropertyMap newMap = getWiderMap(currentMap, newProperty);
+
final MethodHandle widerSetter = newProperty.getSetter(type, newMap);
- final MethodHandle explodeTypeSetter = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), currentType, type));
- if (currentType != null && currentType.isPrimitive() && type == Object.class) {
- //might try a box check on this to avoid widening field to object storage
- mh = createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
- } else {
- mh = explodeTypeSetter;
+ final Class<?> ct = getLocalType();
+ mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap));
+ if (ct != null && ct.isPrimitive() && !type.isPrimitive()) {
+ mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
}
} else {
- mh = generateSetter(forType, type);
+ final Class<?> forType = isUndefined() ? type : getLocalType();
+ mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type);
+ }
+
+ if (isBuiltin()) {
+ mh = MH.filterArguments(mh, 0, debugInvalidate(MH.insertArguments(INVALIDATE_SP, 0, this), getKey()));
}
+ assert mh.type().returnType() == void.class : mh.type();
+
return mh;
}
@Override
- public boolean canChangeType() {
+ public final boolean canChangeType() {
if (OBJECT_FIELDS_ONLY) {
return false;
}
- return currentType != Object.class && (isConfigurable() || isWritable());
- }
-
- private boolean needsInvalidator(final int ti, final int fti) {
- return canChangeType() && ti > fti;
+ // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
+ return getLocalType() == null || (getLocalType() != Object.class && (isConfigurable() || isWritable()));
}
- private void invalidate(final Class<?> newType) {
- getters = new MethodHandle[NOOF_TYPES];
- setCurrentType(newType);
+ private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) {
+ return canChangeType() && typeIndex > currentTypeIndex;
}
- private MethodHandle getSpillGetter() {
- final int slot = getSlot();
- MethodHandle getter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2] : null;
- if (getter == null) {
- getter = MH.insertArguments(SPILL_ELEMENT_GETTER, 1, slot);
- if (slot < SPILL_CACHE_SIZE) {
- SPILL_ACCESSORS[slot * 2 + 0] = getter;
- }
- }
- return getter;
- }
-
- private MethodHandle getSpillSetter() {
- final int slot = getSlot();
- MethodHandle setter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2 + 1] : null;
- if (setter == null) {
- setter = MH.insertArguments(SPILL_ELEMENT_SETTER, 1, slot);
- if (slot < SPILL_CACHE_SIZE) {
- SPILL_ACCESSORS[slot * 2 + 1] = setter;
- }
+ private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
+ if (!Context.DEBUG || !Global.hasInstance()) {
+ return mh;
}
- return setter;
- }
- private static void finest(final String str) {
- if (DEBUG_FIELDS) {
- LOG.finest(str);
+ final Context context = Context.getContextTrusted();
+ assert context != null;
+
+ return context.addLoggingToHandle(
+ ObjectClassGenerator.class,
+ Level.INFO,
+ mh,
+ 0,
+ true,
+ new Supplier<String>() {
+ @Override
+ public String get() {
+ return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')';
+ }
+ });
+ }
+
+ private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
+ if (!Context.DEBUG || !Global.hasInstance()) {
+ return REPLACE_MAP;
}
- }
- private static void info(final String str) {
- if (DEBUG_FIELDS) {
- LOG.info(str);
- }
+ final Context context = Context.getContextTrusted();
+ assert context != null;
+
+ MethodHandle mh = context.addLoggingToHandle(
+ ObjectClassGenerator.class,
+ REPLACE_MAP,
+ new Supplier<String>() {
+ @Override
+ public String get() {
+ return "Type change for '" + getKey() + "' " + oldType + "=>" + newType;
+ }
+ });
+
+ mh = context.addLoggingToHandle(
+ ObjectClassGenerator.class,
+ Level.FINEST,
+ mh,
+ Integer.MAX_VALUE,
+ false,
+ new Supplier<String>() {
+ @Override
+ public String get() {
+ return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap;
+ }
+ });
+ return mh;
}
- private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
- if (DEBUG_FIELDS) {
- return MethodHandleFactory.addDebugPrintout(
- LOG,
- mh,
- tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", forType=" + stripName(forType) + ", type=" + stripName(type) + ')');
+ private static MethodHandle debugInvalidate(final MethodHandle invalidator, final String key) {
+ if (!Context.DEBUG || !Global.hasInstance()) {
+ return invalidator;
}
- return mh;
- }
- private void setCurrentType(final Class<?> currentType) {
- this.currentType = currentType;
- }
+ final Context context = Context.getContextTrusted();
+ assert context != null;
- @Override
- public Class<?> getCurrentType() {
- return currentType;
+ return context.addLoggingToHandle(
+ ObjectClassGenerator.class,
+ invalidator,
+ new Supplier<String>() {
+ @Override
+ public String get() {
+ return "Field change callback for " + key + " triggered ";
+ }
+ });
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(lookup, AccessorProperty.class, name, MH.type(rtype, types));
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types));
}
-
}
diff --git a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
new file mode 100644
index 00000000..e4d6ccb1
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+
+/**
+ * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as
+ * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a
+ * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority
+ * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would
+ * otherwise be lost to identical tuples of (map, className, handle) fields.
+ */
+final class AllocationStrategy implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0));
+
+ /** Allocator map from allocator descriptor */
+ private final PropertyMap allocatorMap;
+
+ /** Name of class where allocator function resides */
+ private final String allocatorClassName;
+
+ /** lazily generated allocator */
+ private transient MethodHandle allocator;
+
+ private AllocationStrategy(final AllocatorDescriptor desc) {
+ this.allocatorMap = desc.getAllocatorMap();
+ // These classes get loaded, so an interned variant of their name is most likely around anyway.
+ this.allocatorClassName = desc.getAllocatorClassName().intern();
+ }
+
+ private boolean matches(final AllocatorDescriptor desc) {
+ return desc.getAllocatorMap().size() == allocatorMap.size() &&
+ desc.getAllocatorClassName().equals(allocatorClassName);
+ }
+
+ static AllocationStrategy get(final AllocatorDescriptor desc) {
+ return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc);
+ }
+
+ PropertyMap getAllocatorMap() {
+ return allocatorMap;
+ }
+
+ ScriptObject allocate(final PropertyMap map) {
+ try {
+ if (allocator == null) {
+ allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName),
+ CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
+ }
+ return (ScriptObject)allocator.invokeExact(map);
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ private Object readResolve() {
+ if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() &&
+ allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) {
+ return DEFAULT_STRATEGY;
+ }
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
+ allocatorMap.size() + "]";
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/AstDeserializer.java b/src/jdk/nashorn/internal/runtime/AstDeserializer.java
new file mode 100644
index 00000000..8f276614
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/AstDeserializer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.zip.InflaterInputStream;
+import jdk.nashorn.internal.ir.FunctionNode;
+
+/**
+ * This static utility class performs deserialization of FunctionNode ASTs from a byte array.
+ * The format is a standard Java serialization stream, deflated.
+ */
+final class AstDeserializer {
+ static FunctionNode deserialize(final byte[] serializedAst) {
+ try {
+ return (FunctionNode)new ObjectInputStream(new InflaterInputStream(new ByteArrayInputStream(
+ serializedAst))).readObject();
+ } catch (final ClassNotFoundException | IOException e) {
+ // This is internal, can't happen
+ throw new AssertionError("Unexpected exception deserializing function", e);
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/CodeInstaller.java b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
index 579b6f3e..e2b5afe8 100644
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.runtime;
+import java.util.Collection;
import java.util.Map;
import jdk.nashorn.internal.codegen.ClassEmitter;
@@ -48,12 +49,20 @@ public interface CodeInstaller<T> {
public T getOwner();
/**
- * Install a class
+ * Install a class.
* @param className name of the class with / separation
* @param bytecode bytecode
* @return the installed class
*/
- public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants);
+ public Class<?> install(final String className, final byte[] bytecode);
+
+ /**
+ * Initialize already installed classes.
+ * @param classes the class to initialize
+ * @param source the source object for the classes
+ * @param constants the runtime constants for the classes
+ */
+ public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants);
/**
* Verify generated bytecode before emission. This is called back from the
@@ -71,17 +80,41 @@ public interface CodeInstaller<T> {
public long getUniqueScriptId();
/**
- * Get next unique eval id
- * @return unique eval id
- */
- public long getUniqueEvalId();
-
- /**
* Store a compiled script for later reuse
+ *
+ * @param cacheKey key to use in cache
* @param source the script source
* @param mainClassName the main class name
* @param classBytes map of class names to class bytes
+ * @param initializers compilation id -> FunctionInitializer map
* @param constants constants array
+ * @param compilationId compilation id
+ */
+ public void storeScript(final String cacheKey, final Source source, final String mainClassName, final Map<String, byte[]> classBytes,
+ final Map<Integer, FunctionInitializer> initializers, final Object[] constants, final int compilationId);
+
+ /**
+ * Load a previously compiled script
+ * @param source the script source
+ * @param functionKey the function id and signature
+ * @return compiled script data
+ */
+ public StoredScript loadScript(Source source, String functionKey);
+
+ /**
+ * Returns a new code installer that shares most of the functionality of this code installer, but uses a
+ * new, independent class loader.
+ * @return a new code installer with a new independent class loader.
*/
- public void storeCompiledScript(Source source, String mainClassName, Map<String, byte[]> classBytes, Object[] constants);
+ public CodeInstaller<T> withNewLoader();
+
+ /**
+ * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
+ * an equivalence relation, and installers are supposed to be compatible with those they create using
+ * {@link #withNewLoader()}.
+ * @param other the other code installer tested for compatibility with this code installer.
+ * @return true if this code installer is compatible with the other code installer.
+ */
+ public boolean isCompatibleWith(CodeInstaller<T> other);
+
}
diff --git a/src/jdk/nashorn/internal/runtime/CodeStore.java b/src/jdk/nashorn/internal/runtime/CodeStore.java
index 8f595999..4e745ff4 100644
--- a/src/jdk/nashorn/internal/runtime/CodeStore.java
+++ b/src/jdk/nashorn/internal/runtime/CodeStore.java
@@ -34,145 +34,309 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.util.Base64;
+import java.util.Iterator;
import java.util.Map;
+import java.util.ServiceLoader;
+import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* A code cache for persistent caching of compiled scripts.
*/
-final class CodeStore {
+@Logger(name="codestore")
+public abstract class CodeStore implements Loggable {
- private final File dir;
- private final int minSize;
-
- // Message digest to file name encoder
- private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+ /**
+ * Permission needed to provide a CodeStore instance via ServiceLoader.
+ */
+ public final static String NASHORN_PROVIDE_CODE_STORE = "nashorn.provideCodeStore";
- // Default minimum size for storing a compiled script class
- private final static int DEFAULT_MIN_SIZE = 1000;
+ private DebugLogger log;
/**
* Constructor
- * @param path directory to store code in
- * @throws IOException
*/
- public CodeStore(final String path) throws IOException {
- this(path, DEFAULT_MIN_SIZE);
+ protected CodeStore() {
}
- /**
- * Constructor
- * @param path directory to store code in
- * @param minSize minimum file size for caching scripts
- * @throws IOException
- */
- public CodeStore(final String path, final int minSize) throws IOException {
- this.dir = checkDirectory(path);
- this.minSize = minSize;
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ log = context.getLogger(getClass());
+ return log;
}
- private static File checkDirectory(final String path) throws IOException {
- try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
- @Override
- public File run() throws IOException {
- final File dir = new File(path).getAbsoluteFile();
- if (!dir.exists() && !dir.mkdirs()) {
- throw new IOException("Could not create directory: " + dir);
- } else if (!dir.isDirectory()) {
- throw new IOException("Not a directory: " + dir);
- } else if (!dir.canRead() || !dir.canWrite()) {
- throw new IOException("Directory not readable or writable: " + dir);
- }
- return dir;
- }
- });
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
- }
+ @Override
+ public DebugLogger getLogger() {
+ return log;
}
/**
- * Return a compiled script from the cache, or null if it isn't found.
+ * Returns a new code store instance.
*
- * @param source the source
- * @return the compiled script or null
- * @throws IOException
- * @throws ClassNotFoundException
+ * @param context the current context
+ * @return The instance, or null if code store could not be created
*/
- public CompiledScript getScript(final Source source) throws IOException, ClassNotFoundException {
- if (source.getLength() < minSize) {
- return null;
- }
-
- final String digest = BASE64.encodeToString(source.getDigest());
- final File file = new File(dir, digest);
-
+ public static CodeStore newCodeStore(final Context context) {
+ final Class<CodeStore> baseClass = CodeStore.class;
try {
- return AccessController.doPrivileged(new PrivilegedExceptionAction<CompiledScript>() {
- @Override
- public CompiledScript run() throws IOException, ClassNotFoundException {
- if (!file.exists()) {
- return null;
- }
- try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
- CompiledScript compiledScript = (CompiledScript) in.readObject();
- compiledScript.setSource(source);
- return compiledScript;
- }
- }
- });
- } catch (PrivilegedActionException e) {
- final Exception ex = e.getException();
- if (ex instanceof IOException) {
- throw (IOException) ex;
- } else if (ex instanceof ClassNotFoundException) {
- throw (ClassNotFoundException) ex;
+ // security check first
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission(NASHORN_PROVIDE_CODE_STORE));
+ }
+ final ServiceLoader<CodeStore> services = ServiceLoader.load(baseClass);
+ final Iterator<CodeStore> iterator = services.iterator();
+ if (iterator.hasNext()) {
+ final CodeStore store = iterator.next();
+ store.initLogger(context).info("using code store provider ", store.getClass().getCanonicalName());
+ return store;
}
- throw (new RuntimeException(ex));
+ } catch (final AccessControlException e) {
+ context.getLogger(CodeStore.class).warning("failed to load code store provider ", e);
+ }
+ try {
+ final CodeStore store = new DirectoryCodeStore(context);
+ store.initLogger(context);
+ return store;
+ } catch (final IOException e) {
+ context.getLogger(CodeStore.class).warning("failed to create cache directory ", e);
+ return null;
}
}
+
/**
* Store a compiled script in the cache.
*
+ * @param functionKey the function key
+ * @param source the source
+ * @param mainClassName the main class name
+ * @param classBytes a map of class bytes
+ * @param initializers the function initializers
+ * @param constants the constants array
+ * @param compilationId the compilation id
+ *
+ * @return stored script
+ */
+ public StoredScript store(final String functionKey,
+ final Source source,
+ final String mainClassName,
+ final Map<String, byte[]> classBytes,
+ final Map<Integer, FunctionInitializer> initializers,
+ final Object[] constants,
+ final int compilationId) {
+ return store(functionKey, source, storedScriptFor(source, mainClassName, classBytes, initializers, constants, compilationId));
+ }
+
+ /**
+ * Stores a compiled script.
+ *
+ * @param functionKey the function key
+ * @param source the source
+ * @param script The compiled script
+ * @return The compiled script or {@code null} if not stored
+ */
+ public abstract StoredScript store(final String functionKey,
+ final Source source,
+ final StoredScript script);
+
+ /**
+ * Return a compiled script from the cache, or null if it isn't found.
+ *
+ * @param source the source
+ * @param functionKey the function key
+ * @return the stored script or null
+ */
+ public abstract StoredScript load(final Source source, final String functionKey);
+
+ /**
+ * Returns a new StoredScript instance.
+ *
* @param source the source
* @param mainClassName the main class name
* @param classBytes a map of class bytes
+ * @param initializers function initializers
* @param constants the constants array
- * @throws IOException
+ * @param compilationId the compilation id
+ *
+ * @return The compiled script
*/
- public void putScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants)
- throws IOException {
- if (source.getLength() < minSize) {
- return;
- }
+ public StoredScript storedScriptFor(final Source source, final String mainClassName,
+ final Map<String, byte[]> classBytes,
+ final Map<Integer, FunctionInitializer> initializers,
+ final Object[] constants, final int compilationId) {
for (final Object constant : constants) {
// Make sure all constant data is serializable
- if (! (constant instanceof Serializable)) {
- return;
+ if (!(constant instanceof Serializable)) {
+ getLogger().warning("cannot store ", source, " non serializable constant ", constant);
+ return null;
}
}
+ return new StoredScript(compilationId, mainClassName, classBytes, initializers, constants);
+ }
+
+ /**
+ * Generate a string representing the function with {@code functionId} and {@code paramTypes}.
+ * @param functionId function id
+ * @param paramTypes parameter types
+ * @return a string representing the function
+ */
+ public static String getCacheKey(final int functionId, final Type[] paramTypes) {
+ final StringBuilder b = new StringBuilder().append(functionId);
+ if(paramTypes != null && paramTypes.length > 0) {
+ b.append('-');
+ for(final Type t: paramTypes) {
+ b.append(Type.getShortSignatureDescriptor(t));
+ }
+ }
+ return b.toString();
+ }
- final String digest = BASE64.encodeToString(source.getDigest());
- final File file = new File(dir, digest);
- final CompiledScript script = new CompiledScript(source, mainClassName, classBytes, constants);
+ /**
+ * A store using a file system directory.
+ */
+ public static class DirectoryCodeStore extends CodeStore {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws IOException {
- try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
- out.writeObject(script);
+ // Default minimum size for storing a compiled script class
+ private final static int DEFAULT_MIN_SIZE = 1000;
+
+ private final File dir;
+ private final boolean readOnly;
+ private final int minSize;
+
+ /**
+ * Constructor
+ *
+ * @param context the current context
+ * @throws IOException if there are read/write problems with the cache and cache directory
+ */
+ public DirectoryCodeStore(final Context context) throws IOException {
+ this(context, Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param context the current context
+ * @param path directory to store code in
+ * @param readOnly is this a read only code store
+ * @param minSize minimum file size for caching scripts
+ * @throws IOException if there are read/write problems with the cache and cache directory
+ */
+ public DirectoryCodeStore(final Context context, final String path, final boolean readOnly, final int minSize) throws IOException {
+ this.dir = checkDirectory(path, context.getEnv(), readOnly);
+ this.readOnly = readOnly;
+ this.minSize = minSize;
+ }
+
+ private static File checkDirectory(final String path, final ScriptEnvironment env, final boolean readOnly) throws IOException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
+ @Override
+ public File run() throws IOException {
+ final File dir = new File(path, getVersionDir(env)).getAbsoluteFile();
+ if (readOnly) {
+ if (!dir.exists() || !dir.isDirectory()) {
+ throw new IOException("Not a directory: " + dir.getPath());
+ } else if (!dir.canRead()) {
+ throw new IOException("Directory not readable: " + dir.getPath());
+ }
+ } else if (!dir.exists() && !dir.mkdirs()) {
+ throw new IOException("Could not create directory: " + dir.getPath());
+ } else if (!dir.isDirectory()) {
+ throw new IOException("Not a directory: " + dir.getPath());
+ } else if (!dir.canRead() || !dir.canWrite()) {
+ throw new IOException("Directory not readable or writable: " + dir.getPath());
+ }
+ return dir;
+ }
+ });
+ } catch (final PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ }
+
+ private static String getVersionDir(final ScriptEnvironment env) throws IOException {
+ try {
+ final String versionDir = OptimisticTypesPersistence.getVersionDirName();
+ return env._optimistic_types ? versionDir + "_opt" : versionDir;
+ } catch (final Exception e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public StoredScript load(final Source source, final String functionKey) {
+ if (source.getLength() < minSize) {
+ return null;
+ }
+
+ final File file = getCacheFile(source, functionKey);
+
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<StoredScript>() {
+ @Override
+ public StoredScript run() throws IOException, ClassNotFoundException {
+ if (!file.exists()) {
+ return null;
+ }
+ try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
+ final StoredScript storedScript = (StoredScript) in.readObject();
+ getLogger().info("loaded ", source, "-", functionKey);
+ return storedScript;
+ }
+ }
+ });
+ } catch (final PrivilegedActionException e) {
+ getLogger().warning("failed to load ", source, "-", functionKey, ": ", e.getException());
+ return null;
+ }
+ }
+
+ @Override
+ public StoredScript store(final String functionKey, final Source source, final StoredScript script) {
+ if (readOnly || script == null || belowThreshold(source)) {
+ return null;
+ }
+
+ final File file = getCacheFile(source, functionKey);
+
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<StoredScript>() {
+ @Override
+ public StoredScript run() throws IOException {
+ try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
+ out.writeObject(script);
+ }
+ getLogger().info("stored ", source, "-", functionKey);
+ return script;
}
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- throw (IOException) e.getException();
+ });
+ } catch (final PrivilegedActionException e) {
+ getLogger().warning("failed to store ", script, "-", functionKey, ": ", e.getException());
+ return null;
+ }
+ }
+
+
+ private File getCacheFile(final Source source, final String functionKey) {
+ return new File(dir, source.getDigest() + '-' + functionKey);
+ }
+
+ private boolean belowThreshold(final Source source) {
+ if (source.getLength() < minSize) {
+ getLogger().info("below size threshold ", source);
+ return true;
+ }
+ return false;
}
}
}
diff --git a/src/jdk/nashorn/internal/runtime/CompiledFunction.java b/src/jdk/nashorn/internal/runtime/CompiledFunction.java
index 18b20a3d..ce20ed31 100644
--- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java
+++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java
@@ -24,97 +24,301 @@
*/
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-
+import java.lang.invoke.MutableCallSite;
+import java.lang.invoke.SwitchPoint;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
+import jdk.nashorn.internal.codegen.TypeMap;
+import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
+import jdk.nashorn.internal.runtime.events.RecompilationEvent;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
/**
* An version of a JavaScript function, native or JavaScript.
* Supports lazily generating a constructor version of the invocation.
*/
-final class CompiledFunction implements Comparable<CompiledFunction> {
-
- /** The method type may be more specific than the invoker, if. e.g.
- * the invoker is guarded, and a guard with a generic object only
- * fallback, while the target is more specific, we still need the
- * more specific type for sorting */
- private final MethodType type;
- private final MethodHandle invoker;
+final class CompiledFunction {
+
+ private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
+ private static final MethodHandle RELINK_COMPOSABLE_INVOKER = findOwnMH("relinkComposableInvoker", void.class, CallSite.class, CompiledFunction.class, boolean.class);
+ private static final MethodHandle HANDLE_REWRITE_EXCEPTION = findOwnMH("handleRewriteException", MethodHandle.class, CompiledFunction.class, OptimismInfo.class, RewriteException.class);
+ private static final MethodHandle RESTOF_INVOKER = MethodHandles.exactInvoker(MethodType.methodType(Object.class, RewriteException.class));
+
+ private final DebugLogger log;
+
+ static final Collection<CompiledFunction> NO_FUNCTIONS = Collections.emptySet();
+
+ /**
+ * The method type may be more specific than the invoker, if. e.g.
+ * the invoker is guarded, and a guard with a generic object only
+ * fallback, while the target is more specific, we still need the
+ * more specific type for sorting
+ */
+ private MethodHandle invoker;
private MethodHandle constructor;
+ private OptimismInfo optimismInfo;
+ private final int flags; // from FunctionNode
+ private final MethodType callSiteType;
+
+ private final Specialization specialization;
- CompiledFunction(final MethodType type, final MethodHandle invoker) {
- this(type, invoker, null);
+ CompiledFunction(final MethodHandle invoker) {
+ this(invoker, null, null);
}
- CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
- assert type != null;
- this.type = type;
- this.invoker = invoker;
+ static CompiledFunction createBuiltInConstructor(final MethodHandle invoker, final Specialization specialization) {
+ return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), specialization);
+ }
+
+ CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final Specialization specialization) {
+ this(invoker, constructor, 0, null, specialization, DebugLogger.DISABLED_LOGGER);
+ }
+
+ CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final Specialization specialization, final DebugLogger log) {
+ this.specialization = specialization;
+ if (specialization != null && specialization.isOptimistic()) {
+ /*
+ * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it
+ * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them
+ * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior
+ * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version
+ * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several
+ * candidate methods in Native* that would benefit from this, but I haven't had time to implement any
+ * of them currently. In order to fit in with the relinking framework, the current thinking is
+ * that the methods still take a program point to fit in with other optimistic functions, but
+ * it is set to "first", which is the beginning of the method. The relinker can tell the difference
+ * between builtin and JavaScript functions. This might change. TODO
+ */
+ this.invoker = MH.insertArguments(invoker, invoker.type().parameterCount() - 1, UnwarrantedOptimismException.FIRST_PROGRAM_POINT);
+ throw new AssertionError("Optimistic (UnwarrantedOptimismException throwing) builtin functions are currently not in use");
+ }
+ this.invoker = invoker;
this.constructor = constructor;
+ this.flags = flags;
+ this.callSiteType = callSiteType;
+ this.log = log;
}
- @Override
- public String toString() {
- return "<callSiteType= " + type + " invoker=" + invoker + " ctor=" + constructor + ">";
+ CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData,
+ final Map<Integer, Type> invalidatedProgramPoints, final MethodType callSiteType, final int flags) {
+ this(invoker, null, flags, callSiteType, null, functionData.getLogger());
+ if ((flags & FunctionNode.IS_DEOPTIMIZABLE) != 0) {
+ optimismInfo = new OptimismInfo(functionData, invalidatedProgramPoints);
+ } else {
+ optimismInfo = null;
+ }
}
- MethodHandle getInvoker() {
- return invoker;
+ static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) {
+ return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)), null);
}
- MethodHandle getConstructor() {
- return constructor;
+ boolean isSpecialization() {
+ return specialization != null;
}
- void setConstructor(final MethodHandle constructor) {
- this.constructor = constructor;
+ boolean hasLinkLogic() {
+ return getLinkLogicClass() != null;
}
- boolean hasConstructor() {
- return constructor != null;
+ Class<? extends LinkLogic> getLinkLogicClass() {
+ if (isSpecialization()) {
+ final Class<? extends LinkLogic> linkLogicClass = specialization.getLinkLogicClass();
+ assert !LinkLogic.isEmpty(linkLogicClass) : "empty link logic classes should have been removed by nasgen";
+ return linkLogicClass;
+ }
+ return null;
}
- MethodType type() {
- return type;
+ int getFlags() {
+ return flags;
+ }
+
+ /**
+ * An optimistic specialization is one that can throw UnwarrantedOptimismException.
+ * This is allowed for native methods, as long as they are functional, i.e. don't change
+ * any state between entering and throwing the UOE. Then we can re-execute a wider version
+ * of the method in the continuation. Rest-of method generation for optimistic builtins is
+ * of course not possible, but this approach works and fits into the same relinking
+ * framework
+ *
+ * @return true if optimistic builtin
+ */
+ boolean isOptimistic() {
+ return isSpecialization() ? specialization.isOptimistic() : false;
+ }
+
+ boolean isApplyToCall() {
+ return (flags & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0;
+ }
+
+ boolean isVarArg() {
+ return isVarArgsType(invoker.type());
}
@Override
- public int compareTo(final CompiledFunction o) {
- return compareMethodTypes(type(), o.type());
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ final Class<? extends LinkLogic> linkLogicClass = getLinkLogicClass();
+
+ sb.append("[invokerType=").
+ append(invoker.type()).
+ append(" ctor=").
+ append(constructor).
+ append(" weight=").
+ append(weight()).
+ append(" linkLogic=").
+ append(linkLogicClass != null ? linkLogicClass.getSimpleName() : "none");
+
+ return sb.toString();
+ }
+
+ boolean needsCallee() {
+ return ScriptFunctionData.needsCallee(invoker);
}
- private static int compareMethodTypes(final MethodType ownType, final MethodType otherType) {
- // Comparable interface demands that compareTo() should only return 0 if objects are equal.
- // Failing to meet this requirement causes same weight functions to replace each other in TreeSet,
- // so we go some lengths to come up with an ordering between same weight functions,
- // first falling back to parameter count and then to hash code.
- if (ownType.equals(otherType)) {
- return 0;
+ /**
+ * Returns an invoker method handle for this function. Note that the handle is safely composable in
+ * the sense that you can compose it with other handles using any combinators even if you can't affect call site
+ * invalidation. If this compiled function is non-optimistic, then it returns the same value as
+ * {@link #getInvokerOrConstructor(boolean)}. However, if the function is optimistic, then this handle will
+ * incur an overhead as it will add an intermediate internal call site that can relink itself when the function
+ * needs to regenerate its code to always point at the latest generated code version.
+ * @return a guaranteed composable invoker method handle for this function.
+ */
+ MethodHandle createComposableInvoker() {
+ return createComposableInvoker(false);
+ }
+
+ /**
+ * Returns an invoker method handle for this function when invoked as a constructor. Note that the handle should be
+ * considered non-composable in the sense that you can only compose it with other handles using any combinators if
+ * you can ensure that the composition is guarded by {@link #getOptimisticAssumptionsSwitchPoint()} if it's
+ * non-null, and that you can relink the call site it is set into as a target if the switch point is invalidated. In
+ * all other cases, use {@link #createComposableConstructor()}.
+ * @return a direct constructor method handle for this function.
+ */
+ private MethodHandle getConstructor() {
+ if (constructor == null) {
+ constructor = createConstructorFromInvoker(createInvokerForPessimisticCaller());
}
- final int diff = weight(ownType) - weight(otherType);
- if (diff != 0) {
- return diff;
+ return constructor;
+ }
+
+ /**
+ * Creates a version of the invoker intended for a pessimistic caller (return type is Object, no caller optimistic
+ * program point available).
+ * @return a version of the invoker intended for a pessimistic caller.
+ */
+ private MethodHandle createInvokerForPessimisticCaller() {
+ return createInvoker(Object.class, INVALID_PROGRAM_POINT);
+ }
+
+ /**
+ * Compose a constructor from an invoker.
+ *
+ * @param invoker invoker
+ * @return the composed constructor
+ */
+ private static MethodHandle createConstructorFromInvoker(final MethodHandle invoker) {
+ final boolean needsCallee = ScriptFunctionData.needsCallee(invoker);
+ // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
+ // "this" in the first argument position is what allows the elegant folded composition of
+ // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
+ // always returns Object.
+ final MethodHandle swapped = needsCallee ? swapCalleeAndThis(invoker) : invoker;
+
+ final MethodHandle returnsObject = MH.asType(swapped, swapped.type().changeReturnType(Object.class));
+
+ final MethodType ctorType = returnsObject.type();
+
+ // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
+ // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
+ // (this, [callee, ]args...) => ([callee, ]args...)
+ final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();
+
+ // Fold constructor into newFilter that replaces the return value from the constructor with the originally
+ // allocated value when the originally allocated value is a JS primitive (String, Boolean, Number).
+ // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
+ final MethodHandle filtered = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), returnsObject);
+
+ // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
+ if (needsCallee) {
+ // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
+ // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
+ // or...
+ return MH.foldArguments(filtered, ScriptFunction.ALLOCATE);
}
- if (ownType.parameterCount() != otherType.parameterCount()) {
- return ownType.parameterCount() - otherType.parameterCount();
+
+ // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
+ // (this, args...) filter (callee) => (callee, args...)
+ return MH.filterArguments(filtered, 0, ScriptFunction.ALLOCATE);
+ }
+
+ /**
+ * Permutes the parameters in the method handle from {@code (callee, this, ...)} to {@code (this, callee, ...)}.
+ * Used when creating a constructor handle.
+ * @param mh a method handle with order of arguments {@code (callee, this, ...)}
+ * @return a method handle with order of arguments {@code (this, callee, ...)}
+ */
+ private static MethodHandle swapCalleeAndThis(final MethodHandle mh) {
+ final MethodType type = mh.type();
+ assert type.parameterType(0) == ScriptFunction.class : type;
+ assert type.parameterType(1) == Object.class : type;
+ final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class);
+ final int[] reorder = new int[type.parameterCount()];
+ reorder[0] = 1;
+ assert reorder[1] == 0;
+ for (int i = 2; i < reorder.length; ++i) {
+ reorder[i] = i;
}
- // We're just interested in not returning 0 here, not correct ordering
- return ownType.hashCode() - otherType.hashCode();
+ return MethodHandles.permuteArguments(mh, newType, reorder);
}
- @Override
- public boolean equals(Object obj) {
- return obj instanceof CompiledFunction && type().equals(((CompiledFunction)obj).type());
+ /**
+ * Returns an invoker method handle for this function when invoked as a constructor. Note that the handle is safely
+ * composable in the sense that you can compose it with other handles using any combinators even if you can't affect
+ * call site invalidation. If this compiled function is non-optimistic, then it returns the same value as
+ * {@link #getConstructor()}. However, if the function is optimistic, then this handle will incur an overhead as it
+ * will add an intermediate internal call site that can relink itself when the function needs to regenerate its code
+ * to always point at the latest generated code version.
+ * @return a guaranteed composable constructor method handle for this function.
+ */
+ MethodHandle createComposableConstructor() {
+ return createComposableInvoker(true);
}
- @Override
- public int hashCode() {
- return type().hashCode();
+ boolean hasConstructor() {
+ return constructor != null;
+ }
+
+ MethodType type() {
+ return invoker.type();
}
- private int weight() {
+ int weight() {
return weight(type());
}
@@ -124,76 +328,645 @@ final class CompiledFunction implements Comparable<CompiledFunction> {
}
int weight = Type.typeFor(type.returnType()).getWeight();
- for (final Class<?> paramType : type.parameterArray()) {
+ for (int i = 0 ; i < type.parameterCount() ; i++) {
+ final Class<?> paramType = type.parameterType(i);
final int pweight = Type.typeFor(paramType).getWeight() * 2; //params are more important than call types as return values are always specialized
weight += pweight;
}
+
+ weight += type.parameterCount(); //more params outweigh few parameters
+
return weight;
}
- private static boolean isVarArgsType(final MethodType type) {
+ static boolean isVarArgsType(final MethodType type) {
assert type.parameterCount() >= 1 : type;
return type.parameterType(type.parameterCount() - 1) == Object[].class;
}
- boolean moreGenericThan(final CompiledFunction o) {
- return weight() > o.weight();
+ static boolean moreGenericThan(final MethodType mt0, final MethodType mt1) {
+ return weight(mt0) > weight(mt1);
}
- boolean moreGenericThan(final MethodType mt) {
- return weight() > weight(mt);
+ boolean betterThanFinal(final CompiledFunction other, final MethodType callSiteMethodType) {
+ // Prefer anything over nothing, as we can't compile new versions.
+ if (other == null) {
+ return true;
+ }
+ return betterThanFinal(this, other, callSiteMethodType);
}
- /**
- * Check whether a given method descriptor is compatible with this invocation.
- * It is compatible if the types are narrower than the invocation type so that
- * a semantically equivalent linkage can be performed.
- *
- * @param mt type to check against
- * @return true if types are compatible
- */
- boolean typeCompatible(final MethodType mt) {
- final int wantedParamCount = mt.parameterCount();
- final int existingParamCount = type.parameterCount();
-
- //if we are not examining a varargs type, the number of parameters must be the same
- if (wantedParamCount != existingParamCount && !isVarArgsType(mt)) {
+ private static boolean betterThanFinal(final CompiledFunction cf, final CompiledFunction other, final MethodType callSiteMethodType) {
+ final MethodType thisMethodType = cf.type();
+ final MethodType otherMethodType = other.type();
+ final int thisParamCount = getParamCount(thisMethodType);
+ final int otherParamCount = getParamCount(otherMethodType);
+ final int callSiteRawParamCount = getParamCount(callSiteMethodType);
+ final boolean csVarArg = callSiteRawParamCount == Integer.MAX_VALUE;
+ // Subtract 1 for callee for non-vararg call sites
+ final int callSiteParamCount = csVarArg ? callSiteRawParamCount : callSiteRawParamCount - 1;
+
+ // Prefer the function that discards less parameters
+ final int thisDiscardsParams = Math.max(callSiteParamCount - thisParamCount, 0);
+ final int otherDiscardsParams = Math.max(callSiteParamCount - otherParamCount, 0);
+ if(thisDiscardsParams < otherDiscardsParams) {
+ return true;
+ }
+ if(thisDiscardsParams > otherDiscardsParams) {
return false;
}
- //we only go as far as the shortest array. the only chance to make this work if
- //parameters lengths do not match is if our type ends with a varargs argument.
- //then every trailing parameter in the given callsite can be folded into it, making
- //us compatible (albeit slower than a direct specialization)
- final int lastParamIndex = Math.min(wantedParamCount, existingParamCount);
- for (int i = 0; i < lastParamIndex; i++) {
- final Type w = Type.typeFor(mt.parameterType(i));
- final Type e = Type.typeFor(type.parameterType(i));
+ final boolean thisVarArg = thisParamCount == Integer.MAX_VALUE;
+ final boolean otherVarArg = otherParamCount == Integer.MAX_VALUE;
+ if(!(thisVarArg && otherVarArg && csVarArg)) {
+ // At least one of them isn't vararg
+ final Type[] thisType = toTypeWithoutCallee(thisMethodType, 0); // Never has callee
+ final Type[] otherType = toTypeWithoutCallee(otherMethodType, 0); // Never has callee
+ final Type[] callSiteType = toTypeWithoutCallee(callSiteMethodType, 1); // Always has callee
+
+ int narrowWeightDelta = 0;
+ int widenWeightDelta = 0;
+ final int minParamsCount = Math.min(Math.min(thisParamCount, otherParamCount), callSiteParamCount);
+ for(int i = 0; i < minParamsCount; ++i) {
+ final int callSiteParamWeight = getParamType(i, callSiteType, csVarArg).getWeight();
+ // Delta is negative for narrowing, positive for widening
+ final int thisParamWeightDelta = getParamType(i, thisType, thisVarArg).getWeight() - callSiteParamWeight;
+ final int otherParamWeightDelta = getParamType(i, otherType, otherVarArg).getWeight() - callSiteParamWeight;
+ // Only count absolute values of narrowings
+ narrowWeightDelta += Math.max(-thisParamWeightDelta, 0) - Math.max(-otherParamWeightDelta, 0);
+ // Only count absolute values of widenings
+ widenWeightDelta += Math.max(thisParamWeightDelta, 0) - Math.max(otherParamWeightDelta, 0);
+ }
- //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
- //we also currently don't support boolean as a javascript function callsite type.
- //it will always box.
- if (w.isBoolean()) {
+ // If both functions accept more arguments than what is passed at the call site, account for ability
+ // to receive Undefined un-narrowed in the remaining arguments.
+ if(!thisVarArg) {
+ for(int i = callSiteParamCount; i < thisParamCount; ++i) {
+ narrowWeightDelta += Math.max(Type.OBJECT.getWeight() - thisType[i].getWeight(), 0);
+ }
+ }
+ if(!otherVarArg) {
+ for(int i = callSiteParamCount; i < otherParamCount; ++i) {
+ narrowWeightDelta -= Math.max(Type.OBJECT.getWeight() - otherType[i].getWeight(), 0);
+ }
+ }
+
+ // Prefer function that narrows less
+ if(narrowWeightDelta < 0) {
+ return true;
+ }
+ if(narrowWeightDelta > 0) {
return false;
}
- //This callsite type has a vararg here. it will swallow all remaining args.
- //for consistency, check that it's the last argument
- if (e.isArray()) {
+ // Prefer function that widens less
+ if(widenWeightDelta < 0) {
return true;
}
+ if(widenWeightDelta > 0) {
+ return false;
+ }
+ }
+
+ // Prefer the function that exactly matches the arity of the call site.
+ if(thisParamCount == callSiteParamCount && otherParamCount != callSiteParamCount) {
+ return true;
+ }
+ if(thisParamCount != callSiteParamCount && otherParamCount == callSiteParamCount) {
+ return false;
+ }
+
+ // Otherwise, neither function matches arity exactly. We also know that at this point, they both can receive
+ // more arguments than call site, otherwise we would've already chosen the one that discards less parameters.
+ // Note that variable arity methods are preferred, as they actually match the call site arity better, since they
+ // really have arbitrary arity.
+ if(thisVarArg) {
+ if(!otherVarArg) {
+ return true; //
+ }
+ } else if(otherVarArg) {
+ return false;
+ }
+
+ // Neither is variable arity; chose the one that has less extra parameters.
+ final int fnParamDelta = thisParamCount - otherParamCount;
+ if(fnParamDelta < 0) {
+ return true;
+ }
+ if(fnParamDelta > 0) {
+ return false;
+ }
+
+ final int callSiteRetWeight = Type.typeFor(callSiteMethodType.returnType()).getWeight();
+ // Delta is negative for narrower return type, positive for wider return type
+ final int thisRetWeightDelta = Type.typeFor(thisMethodType.returnType()).getWeight() - callSiteRetWeight;
+ final int otherRetWeightDelta = Type.typeFor(otherMethodType.returnType()).getWeight() - callSiteRetWeight;
+
+ // Prefer function that returns a less wide return type
+ final int widenRetDelta = Math.max(thisRetWeightDelta, 0) - Math.max(otherRetWeightDelta, 0);
+ if(widenRetDelta < 0) {
+ return true;
+ }
+ if(widenRetDelta > 0) {
+ return false;
+ }
+
+ // Prefer function that returns a less narrow return type
+ final int narrowRetDelta = Math.max(-thisRetWeightDelta, 0) - Math.max(-otherRetWeightDelta, 0);
+ if(narrowRetDelta < 0) {
+ return true;
+ }
+ if(narrowRetDelta > 0) {
+ return false;
+ }
+
+ //if they are equal, pick the specialized one first
+ if (cf.isSpecialization() != other.isSpecialization()) {
+ return cf.isSpecialization(); //always pick the specialized version if we can
+ }
+
+ if (cf.isSpecialization() && other.isSpecialization()) {
+ return cf.getLinkLogicClass() != null; //pick link logic specialization above generic specializations
+ }
+
+ // Signatures are identical
+ throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType);
+ }
+
+ private static Type[] toTypeWithoutCallee(final MethodType type, final int thisIndex) {
+ final int paramCount = type.parameterCount();
+ final Type[] t = new Type[paramCount - thisIndex];
+ for(int i = thisIndex; i < paramCount; ++i) {
+ t[i - thisIndex] = Type.typeFor(type.parameterType(i));
+ }
+ return t;
+ }
+
+ private static Type getParamType(final int i, final Type[] paramTypes, final boolean isVarArg) {
+ final int fixParamCount = paramTypes.length - (isVarArg ? 1 : 0);
+ if(i < fixParamCount) {
+ return paramTypes[i];
+ }
+ assert isVarArg;
+ return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType();
+ }
+
+ boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
+ if (other.equals(this.callSiteType)) {
+ return true;
+ }
+ final MethodType type = type();
+ final int fnParamCount = getParamCount(type);
+ final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
+ if (isVarArg) {
+ return pickVarArg;
+ }
+
+ final int csParamCount = getParamCount(other);
+ final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
+ final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type
+
+ final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
+ final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
+ // We must match all incoming parameters, except "this". Starting from 1 to skip "this".
+ for(int i = 1; i < minParams; ++i) {
+ final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
+ final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
+ if(!fnType.isEquivalentTo(csType)) {
+ return false;
+ }
+ }
- //Our arguments must be at least as wide as the wanted one, if not wider
- if (Type.widest(w, e) != e) {
- //e.g. this invocation takes double and callsite says "object". reject. won't fit
- //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
+ // Must match any undefined parameters to Object type.
+ for(int i = minParams; i < fnParamCountNoCallee; ++i) {
+ if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
return false;
}
}
- return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
+ return true;
+ }
+
+ private static int getParamCount(final MethodType type) {
+ final int paramCount = type.parameterCount();
+ return type.parameterType(paramCount - 1).isArray() ? Integer.MAX_VALUE : paramCount;
+ }
+
+ private boolean canBeDeoptimized() {
+ return optimismInfo != null;
+ }
+
+ private MethodHandle createComposableInvoker(final boolean isConstructor) {
+ final MethodHandle handle = getInvokerOrConstructor(isConstructor);
+
+ // If compiled function is not optimistic, it can't ever change its invoker/constructor, so just return them
+ // directly.
+ if(!canBeDeoptimized()) {
+ return handle;
+ }
+
+ // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itslef
+ // to the compiled function's changed target whenever the optimistic assumptions are invalidated.
+ final CallSite cs = new MutableCallSite(handle.type());
+ relinkComposableInvoker(cs, this, isConstructor);
+ return cs.dynamicInvoker();
+ }
+
+ private static class HandleAndAssumptions {
+ final MethodHandle handle;
+ final SwitchPoint assumptions;
+
+ HandleAndAssumptions(final MethodHandle handle, final SwitchPoint assumptions) {
+ this.handle = handle;
+ this.assumptions = assumptions;
+ }
+
+ GuardedInvocation createInvocation() {
+ return new GuardedInvocation(handle, assumptions);
+ }
+ }
+
+ /**
+ * Returns a pair of an invocation created with a passed-in supplier and a non-invalidated switch point for
+ * optimistic assumptions (or null for the switch point if the function can not be deoptimized). While the method
+ * makes a best effort to return a non-invalidated switch point (compensating for possible deoptimizing
+ * recompilation happening on another thread) it is still possible that by the time this method returns the
+ * switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function.
+ * This is not a problem, though, as these switch points are always used to produce call sites that fall back to
+ * relinking when they are invalidated, and in this case the execution will end up here again. What this method
+ * basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread.
+ * @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the
+ * {@code CompiledFunction} method itself in some capacity.
+ * @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions
+ * switch point that is guaranteed to not have been invalidated before the call to this method (or null if the
+ * function can't be further deoptimized).
+ */
+ private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier<MethodHandle> invocationSupplier) {
+ for(;;) {
+ final MethodHandle handle = invocationSupplier.get();
+ final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null;
+ if(assumptions != null && assumptions.hasBeenInvalidated()) {
+ // We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit
+ // this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that
+ // the behavior of invalidating the old switch point before recompilation, and only creating the new one
+ // after recompilation is by design. If we didn't wait here for the recompilation to complete, we would
+ // be busy looping through the fallback path of the invalidated switch point, relinking the call site
+ // again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from
+ // the recompilation task we're dependent on. This can still happen if the switch point gets invalidated
+ // after we grabbed it here, in which case we'll indeed do one busy relink immediately.
+ try {
+ wait();
+ } catch (final InterruptedException e) {
+ // Intentionally ignored. There's nothing meaningful we can do if we're interrupted
+ }
+ } else {
+ return new HandleAndAssumptions(handle, assumptions);
+ }
+ }
+ }
+
+ private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) {
+ final HandleAndAssumptions handleAndAssumptions = inv.getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+ @Override
+ public MethodHandle get() {
+ return inv.getInvokerOrConstructor(constructor);
+ }
+ });
+ final MethodHandle handle = handleAndAssumptions.handle;
+ final SwitchPoint assumptions = handleAndAssumptions.assumptions;
+ final MethodHandle target;
+ if(assumptions == null) {
+ target = handle;
+ } else {
+ final MethodHandle relink = MethodHandles.insertArguments(RELINK_COMPOSABLE_INVOKER, 0, cs, inv, constructor);
+ target = assumptions.guardWithTest(handle, MethodHandles.foldArguments(cs.dynamicInvoker(), relink));
+ }
+ cs.setTarget(target.asType(cs.type()));
+ }
+
+ private MethodHandle getInvokerOrConstructor(final boolean selectCtor) {
+ return selectCtor ? getConstructor() : createInvokerForPessimisticCaller();
+ }
+
+ /**
+ * Returns a guarded invocation for this function when not invoked as a constructor. The guarded invocation has no
+ * guard but it potentially has an optimistic assumptions switch point. As such, it will probably not be used as a
+ * final guarded invocation, but rather as a holder for an invocation handle and switch point to be decomposed and
+ * reassembled into a different final invocation by the user of this method. Any recompositions should take care to
+ * continue to use the switch point. If that is not possible, use {@link #createComposableInvoker()} instead.
+ * @return a guarded invocation for an ordinary (non-constructor) invocation of this function.
+ */
+ GuardedInvocation createFunctionInvocation(final Class<?> callSiteReturnType, final int callerProgramPoint) {
+ return getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+ @Override
+ public MethodHandle get() {
+ return createInvoker(callSiteReturnType, callerProgramPoint);
+ }
+ }).createInvocation();
+ }
+
+ /**
+ * Returns a guarded invocation for this function when invoked as a constructor. The guarded invocation has no guard
+ * but it potentially has an optimistic assumptions switch point. As such, it will probably not be used as a final
+ * guarded invocation, but rather as a holder for an invocation handle and switch point to be decomposed and
+ * reassembled into a different final invocation by the user of this method. Any recompositions should take care to
+ * continue to use the switch point. If that is not possible, use {@link #createComposableConstructor()} instead.
+ * @return a guarded invocation for invocation of this function as a constructor.
+ */
+ GuardedInvocation createConstructorInvocation() {
+ return getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+ @Override
+ public MethodHandle get() {
+ return getConstructor();
+ }
+ }).createInvocation();
+ }
+
+ private MethodHandle createInvoker(final Class<?> callSiteReturnType, final int callerProgramPoint) {
+ final boolean isOptimistic = canBeDeoptimized();
+ MethodHandle handleRewriteException = isOptimistic ? createRewriteExceptionHandler() : null;
+
+ MethodHandle inv = invoker;
+ if(isValid(callerProgramPoint)) {
+ inv = OptimisticReturnFilters.filterOptimisticReturnValue(inv, callSiteReturnType, callerProgramPoint);
+ inv = changeReturnType(inv, callSiteReturnType);
+ if(callSiteReturnType.isPrimitive() && handleRewriteException != null) {
+ // because handleRewriteException always returns Object
+ handleRewriteException = OptimisticReturnFilters.filterOptimisticReturnValue(handleRewriteException,
+ callSiteReturnType, callerProgramPoint);
+ }
+ } else if(isOptimistic) {
+ // Required so that rewrite exception has the same return type. It'd be okay to do it even if we weren't
+ // optimistic, but it isn't necessary as the linker upstream will eventually convert the return type.
+ inv = changeReturnType(inv, callSiteReturnType);
+ }
+
+ if(isOptimistic) {
+ assert handleRewriteException != null;
+ final MethodHandle typedHandleRewriteException = changeReturnType(handleRewriteException, inv.type().returnType());
+ return MH.catchException(inv, RewriteException.class, typedHandleRewriteException);
+ }
+ return inv;
+ }
+
+ private MethodHandle createRewriteExceptionHandler() {
+ return MH.foldArguments(RESTOF_INVOKER, MH.insertArguments(HANDLE_REWRITE_EXCEPTION, 0, this, optimismInfo));
+ }
+
+ private static MethodHandle changeReturnType(final MethodHandle mh, final Class<?> newReturnType) {
+ return Bootstrap.getLinkerServices().asType(mh, mh.type().changeReturnType(newReturnType));
+ }
+
+ @SuppressWarnings("unused")
+ private static MethodHandle handleRewriteException(final CompiledFunction function, final OptimismInfo oldOptimismInfo, final RewriteException re) {
+ return function.handleRewriteException(oldOptimismInfo, re);
+ }
+
+ /**
+ * Debug function for printing out all invalidated program points and their
+ * invalidation mapping to next type
+ * @param ipp
+ * @return string describing the ipp map
+ */
+ private static List<String> toStringInvalidations(final Map<Integer, Type> ipp) {
+ if (ipp == null) {
+ return Collections.emptyList();
+ }
+
+ final List<String> list = new ArrayList<>();
+
+ for (final Iterator<Map.Entry<Integer, Type>> iter = ipp.entrySet().iterator(); iter.hasNext(); ) {
+ final Map.Entry<Integer, Type> entry = iter.next();
+ final char bct = entry.getValue().getBytecodeStackType();
+ final String type;
+
+ switch (entry.getValue().getBytecodeStackType()) {
+ case 'A':
+ type = "object";
+ break;
+ case 'I':
+ type = "int";
+ break;
+ case 'J':
+ type = "long";
+ break;
+ case 'D':
+ type = "double";
+ break;
+ default:
+ type = String.valueOf(bct);
+ break;
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append('[').
+ append("program point: ").
+ append(entry.getKey()).
+ append(" -> ").
+ append(type).
+ append(']');
+
+ list.add(sb.toString());
+ }
+
+ return list;
+ }
+
+ private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) {
+ if (log.isEnabled()) {
+ log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type);
+ log.indent();
+ for (final String str : toStringInvalidations(ipp)) {
+ log.fine(str);
+ }
+ log.unindent();
+ }
+ }
+
+ /**
+ * Handles a {@link RewriteException} raised during the execution of this function by recompiling (if needed) the
+ * function with an optimistic assumption invalidated at the program point indicated by the exception, and then
+ * executing a rest-of method to complete the execution with the deoptimized version.
+ * @param oldOptInfo the optimism info of this function. We must store it explicitly as a bound argument in the
+ * method handle, otherwise it could be null for handling a rewrite exception in an outer invocation of a recursive
+ * function when recursive invocations of the function have completely deoptimized it.
+ * @param re the rewrite exception that was raised
+ * @return the method handle for the rest-of method, for folding composition.
+ */
+ private synchronized MethodHandle handleRewriteException(final OptimismInfo oldOptInfo, final RewriteException re) {
+ if (log.isEnabled()) {
+ log.info(
+ new RecompilationEvent(
+ Level.INFO,
+ re,
+ re.getReturnValueNonDestructive()),
+ "caught RewriteException ",
+ re.getMessageShort());
+ log.indent();
+ }
+
+ final MethodType type = type();
+
+ // Compiler needs a call site type as its input, which always has a callee parameter, so we must add it if
+ // this function doesn't have a callee parameter.
+ final MethodType ct = type.parameterType(0) == ScriptFunction.class ?
+ type :
+ type.insertParameterTypes(0, ScriptFunction.class);
+ final OptimismInfo currentOptInfo = optimismInfo;
+ final boolean shouldRecompile = currentOptInfo != null && currentOptInfo.requestRecompile(re);
+
+ // Effective optimism info, for subsequent use. We'll normally try to use the current (latest) one, but if it
+ // isn't available, we'll use the old one bound into the call site.
+ final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
+ FunctionNode fn = effectiveOptInfo.reparse();
+ final boolean serialized = effectiveOptInfo.isSerialized();
+ final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of
+
+ if (!shouldRecompile) {
+ // It didn't necessarily recompile, e.g. for an outer invocation of a recursive function if we already
+ // recompiled a deoptimized version for an inner invocation.
+ // We still need to do the rest of from the beginning
+ logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
+ return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
+ }
+
+ logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
+ fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
+ log.fine("Reusable IR generated");
+
+ // compile the rest of the function, and install it
+ log.info("Generating and installing bytecode from reusable IR...");
+ logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
+ final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL);
+
+ if (effectiveOptInfo.data.usePersistentCodeCache()) {
+ final RecompilableScriptFunctionData data = effectiveOptInfo.data;
+ final int functionNodeId = data.getFunctionNodeId();
+ final TypeMap typeMap = data.typeMap(ct);
+ final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+ final String cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
+ compiler.persistClassInfo(cacheKey, normalFn);
+ }
+
+ final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
+
+ if (log.isEnabled()) {
+ log.unindent();
+ log.info("Done.");
+
+ log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? "can still be deoptimized." : " is completely deoptimized.");
+ log.finest("Looking up invoker...");
+ }
+
+ final MethodHandle newInvoker = effectiveOptInfo.data.lookup(fn);
+ invoker = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType()));
+ constructor = null; // Will be regenerated when needed
+
+ log.info("Done: ", invoker);
+ final MethodHandle restOf = restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL_RESTOF), canBeDeoptimized);
+
+ // Note that we only adjust the switch point after we set the invoker/constructor. This is important.
+ if (canBeDeoptimized) {
+ effectiveOptInfo.newOptimisticAssumptions(); // Otherwise, set a new switch point.
+ } else {
+ optimismInfo = null; // If we got to a point where we no longer have optimistic assumptions, let the optimism info go.
+ }
+ notifyAll();
+
+ return restOf;
}
+ private MethodHandle restOfHandle(final OptimismInfo info, final FunctionNode restOfFunction, final boolean canBeDeoptimized) {
+ assert info != null;
+ assert restOfFunction.getCompileUnit().getUnitClassName().contains("restOf");
+ final MethodHandle restOf =
+ changeReturnType(
+ info.data.lookupCodeMethod(
+ restOfFunction.getCompileUnit().getCode(),
+ MH.type(restOfFunction.getReturnType().getTypeClass(),
+ RewriteException.class)),
+ Object.class);
+
+ if (!canBeDeoptimized) {
+ return restOf;
+ }
+
+ // If rest-of is itself optimistic, we must make sure that we can repeat a deoptimization if it, too hits an exception.
+ return MH.catchException(restOf, RewriteException.class, createRewriteExceptionHandler());
+
+ }
+
+ private static class OptimismInfo {
+ // TODO: this is pointing to its owning ScriptFunctionData. Re-evaluate if that's okay.
+ private final RecompilableScriptFunctionData data;
+ private final Map<Integer, Type> invalidatedProgramPoints;
+ private SwitchPoint optimisticAssumptions;
+ private final DebugLogger log;
+
+ OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
+ this.data = data;
+ this.log = data.getLogger();
+ this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap<Integer, Type>() : invalidatedProgramPoints;
+ newOptimisticAssumptions();
+ }
+
+ private void newOptimisticAssumptions() {
+ optimisticAssumptions = new SwitchPoint();
+ }
+ boolean requestRecompile(final RewriteException e) {
+ final Type retType = e.getReturnType();
+ final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType);
+ if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) {
+ final StackTraceElement[] stack = e.getStackTrace();
+ final String functionId = stack.length == 0 ?
+ data.getName() :
+ stack[0].getClassName() + "." + stack[0].getMethodName();
+
+ log.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
+
+ return false;
+ }
+
+ SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions });
+
+ return true;
+ }
+
+ Compiler getCompiler(final FunctionNode fn, final MethodType actualCallSiteType, final RewriteException e) {
+ return data.getCompiler(fn, actualCallSiteType, e.getRuntimeScope(), invalidatedProgramPoints, getEntryPoints(e));
+ }
+
+ private static int[] getEntryPoints(final RewriteException e) {
+ final int[] prevEntryPoints = e.getPreviousContinuationEntryPoints();
+ final int[] entryPoints;
+ if (prevEntryPoints == null) {
+ entryPoints = new int[1];
+ } else {
+ final int l = prevEntryPoints.length;
+ entryPoints = new int[l + 1];
+ System.arraycopy(prevEntryPoints, 0, entryPoints, 1, l);
+ }
+ entryPoints[0] = e.getProgramPoint();
+ return entryPoints;
+ }
+
+ FunctionNode reparse() {
+ return data.reparse();
+ }
+
+ boolean isSerialized() {
+ return data.isSerialized();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static Object newFilter(final Object result, final Object allocation) {
+ return (result instanceof ScriptObject || !JSType.isPrimitive(result))? result : allocation;
+ }
+
+ private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), CompiledFunction.class, name, MH.type(rtype, types));
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/CompiledFunctions.java b/src/jdk/nashorn/internal/runtime/CompiledFunctions.java
deleted file mode 100644
index ba5ae66c..00000000
--- a/src/jdk/nashorn/internal/runtime/CompiledFunctions.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.nashorn.internal.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.util.Iterator;
-import java.util.TreeSet;
-
-/**
- * This is a list of code versions of a function.
- * The list is sorted in ascending order of generic descriptors
- */
-@SuppressWarnings("serial")
-final class CompiledFunctions extends TreeSet<CompiledFunction> {
-
- private CompiledFunction generic;
-
- CompiledFunction best(final MethodType type) {
- final Iterator<CompiledFunction> iter = iterator();
- while (iter.hasNext()) {
- final CompiledFunction next = iter.next();
- if (next.typeCompatible(type)) {
- return next;
- }
- }
- return generic();
- }
-
- boolean needsCallee() {
- return ScriptFunctionData.needsCallee(mostGeneric().getInvoker());
- }
-
- CompiledFunction mostGeneric() {
- return last();
- }
-
- CompiledFunction generic() {
- CompiledFunction gen = this.generic;
- if (gen == null) {
- gen = this.generic = makeGeneric(mostGeneric());
- }
- return gen;
- }
-
- private static CompiledFunction makeGeneric(final CompiledFunction func) {
- final MethodHandle invoker = composeGenericMethod(func.getInvoker());
- final MethodHandle constructor = func.hasConstructor() ? composeGenericMethod(func.getConstructor()) : null;
- return new CompiledFunction(invoker.type(), invoker, constructor);
- }
-
- /**
- * Takes a method handle, and returns a potentially different method handle that can be used in
- * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}.
- * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into
- * {@code Object} as well, except for the following ones:
- * <ul>
- * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li>
- * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself
- * (callee) as an argument.</li>
- * </ul>
- *
- * @param mh the original method handle
- *
- * @return the new handle, conforming to the rules above.
- */
- private static MethodHandle composeGenericMethod(final MethodHandle mh) {
- final MethodType type = mh.type();
- final boolean isVarArg = ScriptFunctionData.isVarArg(mh);
- final int paramCount = isVarArg ? type.parameterCount() - 1 : type.parameterCount();
-
- MethodType newType = MethodType.genericMethodType(paramCount, isVarArg);
-
- if (ScriptFunctionData.needsCallee(mh)) {
- newType = newType.changeParameterType(0, ScriptFunction.class);
- }
- return type.equals(newType) ? mh : mh.asType(newType);
- }
-
- /**
- * Is the given type even more specific than this entire list? That means
- * we have an opportunity for more specific versions of the method
- * through lazy code generation
- *
- * @param type type to check against
- * @return true if the given type is more specific than all invocations available
- */
- boolean isLessSpecificThan(final MethodType type) {
- return best(type).moreGenericThan(type);
- }
-
-}
diff --git a/src/jdk/nashorn/internal/runtime/ConsString.java b/src/jdk/nashorn/internal/runtime/ConsString.java
index 8f764f4b..a181b0c0 100644
--- a/src/jdk/nashorn/internal/runtime/ConsString.java
+++ b/src/jdk/nashorn/internal/runtime/ConsString.java
@@ -36,8 +36,12 @@ import java.util.Deque;
public final class ConsString implements CharSequence {
private CharSequence left, right;
- final private int length;
- private boolean flat = false;
+ private final int length;
+ private volatile int state = STATE_NEW;
+
+ private final static int STATE_NEW = 0;
+ private final static int STATE_THRESHOLD = 2;
+ private final static int STATE_FLATTENED = -1;
/**
* Constructor
@@ -53,11 +57,14 @@ public final class ConsString implements CharSequence {
this.left = left;
this.right = right;
length = left.length() + right.length();
+ if (length < 0) {
+ throw new IllegalArgumentException("too big concatenated String");
+ }
}
@Override
public String toString() {
- return (String) flattened();
+ return (String) flattened(true);
}
@Override
@@ -67,22 +74,31 @@ public final class ConsString implements CharSequence {
@Override
public char charAt(final int index) {
- return flattened().charAt(index);
+ return flattened(true).charAt(index);
}
@Override
public CharSequence subSequence(final int start, final int end) {
- return flattened().subSequence(start, end);
+ return flattened(true).subSequence(start, end);
+ }
+
+ /**
+ * Returns the components of this ConsString as a {@code CharSequence} array with two elements.
+ * The elements will be either {@code Strings} or other {@code ConsStrings}.
+ * @return CharSequence array of length 2
+ */
+ public synchronized CharSequence[] getComponents() {
+ return new CharSequence[] { left, right };
}
- private CharSequence flattened() {
- if (!flat) {
- flatten();
+ private CharSequence flattened(final boolean flattenNested) {
+ if (state != STATE_FLATTENED) {
+ flatten(flattenNested);
}
return left;
}
- private void flatten() {
+ private synchronized void flatten(final boolean flattenNested) {
// We use iterative traversal as recursion may exceed the stack size limit.
final char[] chars = new char[length];
int pos = length;
@@ -97,8 +113,14 @@ public final class ConsString implements CharSequence {
do {
if (cs instanceof ConsString) {
final ConsString cons = (ConsString) cs;
- stack.addFirst(cons.left);
- cs = cons.right;
+ // Count the times a cons-string is traversed as part of other cons-strings being flattened.
+ // If it crosses a threshold we flatten the nested cons-string internally.
+ if (cons.state == STATE_FLATTENED || (flattenNested && ++cons.state >= STATE_THRESHOLD)) {
+ cs = cons.flattened(false);
+ } else {
+ stack.addFirst(cons.left);
+ cs = cons.right;
+ }
} else {
final String str = (String) cs;
pos -= str.length();
@@ -109,7 +131,7 @@ public final class ConsString implements CharSequence {
left = new String(chars);
right = "";
- flat = true;
+ state = STATE_FLATTENED;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java
index 9f2c521d..9e851998 100644
--- a/src/jdk/nashorn/internal/runtime/Context.java
+++ b/src/jdk/nashorn/internal/runtime/Context.java
@@ -26,10 +26,10 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
@@ -39,11 +39,12 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.concurrent.atomic.AtomicLong;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessControlContext;
@@ -55,20 +56,34 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
+import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
-
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import javax.script.ScriptEngine;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
+import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Parser;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
import jdk.nashorn.internal.runtime.options.Options;
/**
@@ -111,6 +126,19 @@ public final class Context {
private static final String LOAD_FX = "fx:";
private static final String LOAD_NASHORN = "nashorn:";
+ private static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+ private static MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class);
+
+ /**
+ * Keeps track of which builtin prototypes and properties have been relinked
+ * Currently we are conservative and associate the name of a builtin class with all
+ * its properties, so it's enough to invalidate a property to break all assumptions
+ * about a prototype. This can be changed to a more fine grained approach, but no one
+ * ever needs this, given the very rare occurance of swapping out only parts of
+ * a builtin v.s. the entire builtin object
+ */
+ private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>();
+
/* Force DebuggerSupport to be loaded. */
static {
DebuggerSupport.FORCELOAD = true;
@@ -124,6 +152,13 @@ public final class Context {
private final Context context;
private final ScriptLoader loader;
private final CodeSource codeSource;
+ private int usageCount = 0;
+ private int bytesDefined = 0;
+
+ // We reuse this installer for 10 compilations or 200000 defined bytes. Usually the first condition
+ // will occur much earlier, the second is a safety measure for very large scripts/functions.
+ private final static int MAX_USAGES = 10;
+ private final static int MAX_BYTES_DEFINED = 200_000;
private ContextCodeInstaller(final Context context, final ScriptLoader loader, final CodeSource codeSource) {
this.context = context;
@@ -132,7 +167,7 @@ public final class Context {
}
/**
- * Return the context for this installer
+ * Return the script environment for this installer
* @return ScriptEnvironment
*/
@Override
@@ -141,32 +176,35 @@ public final class Context {
}
@Override
- public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants) {
- Compiler.LOG.fine("Installing class ", className);
-
+ public Class<?> install(final String className, final byte[] bytecode) {
+ usageCount++;
+ bytesDefined += bytecode.length;
final String binaryName = Compiler.binaryName(className);
- final Class<?> clazz = loader.installClass(binaryName, bytecode, codeSource);
+ return loader.installClass(binaryName, bytecode, codeSource);
+ }
+ @Override
+ public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) {
try {
- // Need doPrivileged because these fields are private
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
- //use reflection to write source and constants table to installed classes
- final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
- final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
- sourceField.setAccessible(true);
- constantsField.setAccessible(true);
- sourceField.set(null, source);
- constantsField.set(null, constants);
+ for (final Class<?> clazz : classes) {
+ //use reflection to write source and constants table to installed classes
+ final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
+ sourceField.setAccessible(true);
+ sourceField.set(null, source);
+
+ final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
+ constantsField.setAccessible(true);
+ constantsField.set(null, constants);
+ }
return null;
}
});
} catch (final PrivilegedActionException e) {
throw new RuntimeException(e);
}
-
- return clazz;
}
@Override
@@ -180,20 +218,38 @@ public final class Context {
}
@Override
- public long getUniqueEvalId() {
- return context.getUniqueEvalId();
+ public void storeScript(final String cacheKey, final Source source, final String mainClassName,
+ final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
+ final Object[] constants, final int compilationId) {
+ if (context.codeStore != null) {
+ context.codeStore.store(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
+ }
}
@Override
- public void storeCompiledScript(final Source source, final String mainClassName,
- final Map<String, byte[]> classBytes, final Object[] constants) {
+ public StoredScript loadScript(final Source source, final String functionKey) {
if (context.codeStore != null) {
- try {
- context.codeStore.putScript(source, mainClassName, classBytes, constants);
- } catch (final IOException e) {
- throw new RuntimeException(e);
- }
+ return context.codeStore.load(source, functionKey);
+ }
+ return null;
+ }
+
+ @Override
+ public CodeInstaller<ScriptEnvironment> withNewLoader() {
+ // Reuse this installer if we're within our limits.
+ if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
+ return this;
}
+ return new ContextCodeInstaller(context, context.createNewLoader(), codeSource);
+ }
+
+ @Override
+ public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
+ if (other instanceof ContextCodeInstaller) {
+ final ContextCodeInstaller cci = (ContextCodeInstaller)other;
+ return cci.context == context && cci.codeSource == codeSource;
+ }
+ return false;
}
}
@@ -208,6 +264,10 @@ public final class Context {
// persistent code store
private CodeStore codeStore;
+ // A factory for linking global properties as constant method handles. It is created when the first Global
+ // is created, and invalidated forever once the second global is created.
+ private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();
+
/**
* Get the current global scope
* @return the current global scope
@@ -236,6 +296,14 @@ public final class Context {
public static void setGlobal(final Global global) {
// This class in a package.access protected package.
// Trusted code only can call this method.
+ assert getGlobal() != global;
+ //same code can be cached between globals, then we need to invalidate method handle constants
+ if (global != null) {
+ final GlobalConstants globalConstants = getContext(global).getGlobalConstants();
+ if (globalConstants != null) {
+ globalConstants.invalidateAll();
+ }
+ }
currentGlobal.set(global);
}
@@ -276,7 +344,6 @@ public final class Context {
* @param str text to write
* @param crlf write a carriage return/new line after text
*/
- @SuppressWarnings("resource")
public static void err(final String str, final boolean crlf) {
final PrintWriter err = Context.getCurrentErr();
if (err != null) {
@@ -309,8 +376,8 @@ public final class Context {
/** Unique id for script. Used only when --loader-per-compile=false */
private final AtomicLong uniqueScriptId;
- /** Unique id for 'eval' */
- private final AtomicLong uniqueEvalId;
+ /** Optional class filter to use for Java classes. Can be null. */
+ private final ClassFilter classFilter;
private static final ClassLoader myLoader = Context.class.getClassLoader();
private static final StructureLoader sharedLoader;
@@ -366,7 +433,19 @@ public final class Context {
* @param appLoader application class loader
*/
public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
- this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader);
+ this(options, errors, appLoader, (ClassFilter)null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param options options from command line or Context creator
+ * @param errors error manger
+ * @param appLoader application class loader
+ * @param classFilter class filter to use
+ */
+ public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader, final ClassFilter classFilter) {
+ this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader, classFilter);
}
/**
@@ -379,11 +458,26 @@ public final class Context {
* @param appLoader application class loader
*/
public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
+ this(options, errors, out, err, appLoader, (ClassFilter)null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param options options from command line or Context creator
+ * @param errors error manger
+ * @param out output writer for this Context
+ * @param err error writer for this Context
+ * @param appLoader application class loader
+ * @param classFilter class filter to use
+ */
+ public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader, final ClassFilter classFilter) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(NASHORN_CREATE_CONTEXT));
}
+ this.classFilter = classFilter;
this.env = new ScriptEnvironment(options, out, err);
this._strict = env._strict;
this.appLoader = appLoader;
@@ -395,12 +489,11 @@ public final class Context {
this.uniqueScriptId = new AtomicLong();
}
this.errors = errors;
- this.uniqueEvalId = new AtomicLong();
// if user passed -classpath option, make a class loader with that and set it as
// thread context class loader so that script can access classes from that path.
final String classPath = options.getString("classpath");
- if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
+ if (!env._compile_only && classPath != null && !classPath.isEmpty()) {
// make sure that caller can create a class loader.
if (sm != null) {
sm.checkPermission(new RuntimePermission("createClassLoader"));
@@ -416,16 +509,7 @@ public final class Context {
}
if (env._persistent_cache) {
- if (env._lazy_compilation || env._specialize_calls != null) {
- getErr().println("Can not use persistent class caching with lazy compilation or call specialization.");
- } else {
- try {
- final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
- codeStore = new CodeStore(cacheDir);
- } catch (IOException e) {
- throw new RuntimeException("Error initializing code cache", e);
- }
- }
+ codeStore = newCodeStore(this);
}
// print version info if asked.
@@ -436,6 +520,26 @@ public final class Context {
if (env._fullversion) {
getErr().println("nashorn full version " + Version.fullVersion());
}
+
+ initLoggers();
+ }
+
+
+ /**
+ * Get the class filter for this context
+ * @return class filter
+ */
+ public ClassFilter getClassFilter() {
+ return classFilter;
+ }
+
+ /**
+ * Returns the factory for constant method handles for global properties. The returned factory can be
+ * invalidated if this Context has more than one Global.
+ * @return the factory for constant method handles for global properties.
+ */
+ GlobalConstants getGlobalConstants() {
+ return globalConstantsRef.get();
}
/**
@@ -512,13 +616,12 @@ public final class Context {
*/
public MultiGlobalCompiledScript compileScript(final Source source) {
final Class<?> clazz = compile(source, this.errors, this._strict);
- final MethodHandle runMethodHandle = getRunScriptHandle(clazz);
- final boolean strict = isStrict(clazz);
+ final MethodHandle createProgramFunctionHandle = getCreateProgramFunctionHandle(clazz);
return new MultiGlobalCompiledScript() {
@Override
public ScriptFunction getFunction(final Global newGlobal) {
- return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict);
+ return invokeCreateProgramFunctionHandle(createProgramFunctionHandle, newGlobal);
}
};
}
@@ -531,15 +634,31 @@ public final class Context {
* @param callThis "this" to be passed to the evaluated code
* @param location location of the eval call
* @param strict is this {@code eval} call from a strict mode code?
+ * @return the return value of the {@code eval}
+ */
+ public Object eval(final ScriptObject initialScope, final String string,
+ final Object callThis, final Object location, final boolean strict) {
+ return eval(initialScope, string, callThis, location, strict, false);
+ }
+
+ /**
+ * Entry point for {@code eval}
+ *
+ * @param initialScope The scope of this eval call
+ * @param string Evaluated code as a String
+ * @param callThis "this" to be passed to the evaluated code
+ * @param location location of the eval call
+ * @param strict is this {@code eval} call from a strict mode code?
+ * @param evalCall is this called from "eval" builtin?
*
* @return the return value of the {@code eval}
*/
- public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
- final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
- final Source source = sourceFor(file, string);
+ public Object eval(final ScriptObject initialScope, final String string,
+ final Object callThis, final Object location, final boolean strict, final boolean evalCall) {
+ final String file = location == UNDEFINED || location == null ? "<eval>" : location.toString();
+ final Source source = sourceFor(file, string, evalCall);
final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
final Global global = Context.getGlobal();
-
ScriptObject scope = initialScope;
// ECMA section 10.1.1 point 2 says eval code is strict if it begins
@@ -581,10 +700,10 @@ public final class Context {
scope = strictEvalScope;
}
- ScriptFunction func = getRunScriptFunction(clazz, scope);
+ final ScriptFunction func = getProgramFunction(clazz, scope);
Object evalThis;
if (directEval) {
- evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
+ evalThis = callThis instanceof ScriptObject || strictFlag ? callThis : global;
} else {
evalThis = global;
}
@@ -603,7 +722,7 @@ public final class Context {
public Source run() {
try {
final URL resURL = Context.class.getResource(resource);
- return (resURL != null)? sourceFor(srcStr, resURL) : null;
+ return resURL != null ? sourceFor(srcStr, resURL) : null;
} catch (final IOException exp) {
return null;
}
@@ -626,7 +745,7 @@ public final class Context {
* @throws IOException if source cannot be found or loaded
*/
public Object load(final ScriptObject scope, final Object from) throws IOException {
- final Object src = (from instanceof ConsString)? from.toString() : from;
+ final Object src = from instanceof ConsString ? from.toString() : from;
Source source = null;
// load accepts a String (which could be a URL or a file name), a File, a URL
@@ -634,8 +753,8 @@ public final class Context {
if (src instanceof String) {
final String srcStr = (String)src;
if (srcStr.startsWith(LOAD_CLASSPATH)) {
- URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
- source = (url != null)? sourceFor(url.toString(), url) : null;
+ final URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
+ source = url != null ? sourceFor(url.toString(), url) : null;
} else {
final File file = new File(srcStr);
if (srcStr.indexOf(':') != -1) {
@@ -739,11 +858,12 @@ public final class Context {
*
* @throws ClassNotFoundException if structure class cannot be resolved
*/
- public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
+ @SuppressWarnings("unchecked")
+ public static Class<? extends ScriptObject> forStructureClass(final String fullName) throws ClassNotFoundException {
if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
throw new ClassNotFoundException(fullName);
}
- return Class.forName(fullName, true, sharedLoader);
+ return (Class<? extends ScriptObject>)Class.forName(fullName, true, sharedLoader);
}
/**
@@ -839,6 +959,11 @@ public final class Context {
throw new ClassNotFoundException(fullName);
}
+ // give chance to ClassFilter to filter out, if present
+ if (classFilter != null && !classFilter.exposeToScripts(fullName)) {
+ throw new ClassNotFoundException(fullName);
+ }
+
// check package access as soon as possible!
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -905,23 +1030,47 @@ public final class Context {
* @return the global script object
*/
public Global newGlobal() {
+ createOrInvalidateGlobalConstants();
return new Global(this);
}
+ private void createOrInvalidateGlobalConstants() {
+ for (;;) {
+ final GlobalConstants currentGlobalConstants = getGlobalConstants();
+ if (currentGlobalConstants != null) {
+ // Subsequent invocation; we're creating our second or later Global. GlobalConstants is not safe to use
+ // with more than one Global, as the constant method handle linkages it creates create a coupling
+ // between the Global and the call sites in the compiled code.
+ currentGlobalConstants.invalidateForever();
+ return;
+ }
+ final GlobalConstants newGlobalConstants = new GlobalConstants(getLogger(GlobalConstants.class));
+ if (globalConstantsRef.compareAndSet(null, newGlobalConstants)) {
+ // First invocation; we're creating the first Global in this Context. Create the GlobalConstants object
+ // for this Context.
+ return;
+ }
+
+ // If we reach here, then we started out as the first invocation, but another concurrent invocation won the
+ // CAS race. We'll just let the loop repeat and invalidate the CAS race winner.
+ }
+ }
+
/**
* Initialize given global scope object.
*
* @param global the global
+ * @param engine the associated ScriptEngine instance, can be null
* @return the initialized global scope object.
*/
- public Global initGlobal(final Global global) {
+ public Global initGlobal(final Global global, final ScriptEngine engine) {
// Need only minimal global object, if we are just compiling.
if (!env._compile_only) {
final Global oldGlobal = Context.getGlobal();
try {
Context.setGlobal(global);
// initialize global scope with builtin global objects
- global.initBuiltinObjects();
+ global.initBuiltinObjects(engine);
} finally {
Context.setGlobal(oldGlobal);
}
@@ -931,15 +1080,33 @@ public final class Context {
}
/**
- * Trusted variant - package-private
+ * Initialize given global scope object.
+ *
+ * @param global the global
+ * @return the initialized global scope object.
*/
+ public Global initGlobal(final Global global) {
+ return initGlobal(global, null);
+ }
/**
* Return the current global's context
* @return current global's context
*/
static Context getContextTrusted() {
- return ((ScriptObject)Context.getGlobal()).getContext();
+ return getContext(getGlobal());
+ }
+
+ static Context getContextTrustedOrNull() {
+ final Global global = Context.getGlobal();
+ return global == null ? null : getContext(global);
+ }
+
+ private static Context getContext(final Global global) {
+ // We can't invoke Global.getContext() directly, as it's a protected override, and Global isn't in our package.
+ // In order to access the method, we must cast it to ScriptObject first (which is in our package) and then let
+ // virtual invocation do its thing.
+ return ((ScriptObject)global).getContext();
}
/**
@@ -983,40 +1150,33 @@ public final class Context {
return ScriptRuntime.apply(script, thiz);
}
- private static MethodHandle getRunScriptHandle(final Class<?> script) {
- return MH.findStatic(
- MethodHandles.lookup(),
- script,
- RUN_SCRIPT.symbolName(),
- MH.type(
- Object.class,
- ScriptFunction.class,
- Object.class));
+ private static ScriptFunction getProgramFunction(final Class<?> script, final ScriptObject scope) {
+ if (script == null) {
+ return null;
+ }
+ return invokeCreateProgramFunctionHandle(getCreateProgramFunctionHandle(script), scope);
}
- private static boolean isStrict(final Class<?> script) {
+ private static MethodHandle getCreateProgramFunctionHandle(final Class<?> script) {
try {
- return script.getField(STRICT_MODE.symbolName()).getBoolean(null);
- } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
- return false;
+ return LOOKUP.findStatic(script, CREATE_PROGRAM_FUNCTION.symbolName(), CREATE_PROGRAM_FUNCTION_TYPE);
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new AssertionError("Failed to retrieve a handle for the program function for " + script.getName(), e);
}
}
- private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
- if (script == null) {
- return null;
+ private static ScriptFunction invokeCreateProgramFunctionHandle(final MethodHandle createProgramFunctionHandle, final ScriptObject scope) {
+ try {
+ return (ScriptFunction)createProgramFunctionHandle.invokeExact(scope);
+ } catch (final RuntimeException|Error e) {
+ throw e;
+ } catch (final Throwable t) {
+ throw new AssertionError("Failed to create a program function", t);
}
-
- // Get run method - the entry point to the script
- final MethodHandle runMethodHandle = getRunScriptHandle(script);
- boolean strict = isStrict(script);
-
- // Package as a JavaScript function and pass function back to shell.
- return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
}
private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
- return getRunScriptFunction(compile(source, errMan, this._strict), scope);
+ return getProgramFunction(compile(source, errMan, this._strict), scope);
}
private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
@@ -1025,35 +1185,37 @@ public final class Context {
Class<?> script = findCachedClass(source);
if (script != null) {
- Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
+ final DebugLogger log = getLogger(Compiler.class);
+ if (log.isEnabled()) {
+ log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
+ }
return script;
}
- CompiledScript compiledScript = null;
+ StoredScript storedScript = null;
FunctionNode functionNode = null;
+ // We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation
+ // just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData.
+ final boolean useCodeStore = codeStore != null && !env._parse_only && !env._optimistic_types;
+ final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
- if (!env._parse_only && codeStore != null) {
- try {
- compiledScript = codeStore.getScript(source);
- } catch (IOException | ClassNotFoundException e) {
- Compiler.LOG.warning("Error loading ", source, " from cache: ", e);
- // Fall back to normal compilation
- }
+ if (useCodeStore) {
+ storedScript = codeStore.load(source, cacheKey);
}
- if (compiledScript == null) {
- functionNode = new Parser(env, source, errMan, strict).parse();
+ if (storedScript == null) {
+ functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
- if (errors.hasErrors()) {
+ if (errMan.hasErrors()) {
return null;
}
- if (env._print_ast) {
+ if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
getErr().println(new ASTWriter(functionNode));
}
- if (env._print_parse) {
- getErr().println(new PrintVisitor(functionNode));
+ if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+ getErr().println(new PrintVisitor(functionNode, true, false));
}
}
@@ -1066,12 +1228,26 @@ public final class Context {
final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
- if (functionNode != null) {
- final Compiler compiler = new Compiler(installer, strict);
- final FunctionNode newFunctionNode = compiler.compile(functionNode);
- script = compiler.install(newFunctionNode);
+ if (storedScript == null) {
+ final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
+
+ final Compiler compiler = new Compiler(
+ this,
+ env,
+ installer,
+ source,
+ errMan,
+ strict | functionNode.isStrict());
+
+ final FunctionNode compiledFunction = compiler.compile(functionNode, phases);
+ if (errMan.hasErrors()) {
+ return null;
+ }
+ script = compiledFunction.getRootClass();
+ compiler.persistClassInfo(cacheKey, compiledFunction);
} else {
- script = install(compiledScript, installer);
+ Compiler.updateCompilationId(storedScript.getCompilationId());
+ script = install(storedScript, source, installer);
}
cacheClass(source, script);
@@ -1088,48 +1264,53 @@ public final class Context {
}, CREATE_LOADER_ACC_CTXT);
}
- private long getUniqueEvalId() {
- return uniqueEvalId.getAndIncrement();
- }
-
private long getUniqueScriptId() {
return uniqueScriptId.getAndIncrement();
}
-
/**
* Install a previously compiled class from the code cache.
*
- * @param compiledScript cached script containing class bytes and constants
+ * @param storedScript cached script containing class bytes and constants
* @return main script class
*/
- private Class<?> install(final CompiledScript compiledScript, final CodeInstaller<ScriptEnvironment> installer) {
+ private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
final Map<String, Class<?>> installedClasses = new HashMap<>();
- final Source source = compiledScript.getSource();
- final Object[] constants = compiledScript.getConstants();
- final String rootClassName = compiledScript.getMainClassName();
- final byte[] rootByteCode = compiledScript.getClassBytes().get(rootClassName);
- final Class<?> rootClass = installer.install(rootClassName, rootByteCode, source, constants);
+ final Map<String, byte[]> classBytes = storedScript.getClassBytes();
+ final Object[] constants = storedScript.getConstants();
+ final String mainClassName = storedScript.getMainClassName();
+ final byte[] mainClassBytes = classBytes.get(mainClassName);
+ final Class<?> mainClass = installer.install(mainClassName, mainClassBytes);
+ final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers();
- installedClasses.put(rootClassName, rootClass);
+ installedClasses.put(mainClassName, mainClass);
- for (final Map.Entry<String, byte[]> entry : compiledScript.getClassBytes().entrySet()) {
+ for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
final String className = entry.getKey();
- if (className.equals(rootClassName)) {
+ if (className.equals(mainClassName)) {
continue;
}
final byte[] code = entry.getValue();
- installedClasses.put(className, installer.install(className, code, source, constants));
+ installedClasses.put(className, installer.install(className, code));
}
- for (Object constant : constants) {
+
+ installer.initialize(installedClasses.values(), source, constants);
+
+ for (final Object constant : constants) {
if (constant instanceof RecompilableScriptFunctionData) {
- ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source);
+ final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
+ data.initTransients(source, installer);
+ final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
+ if (initializer != null) {
+ initializer.setCode(installedClasses.get(initializer.getClassName()));
+ data.initializeCode(initializer);
+ }
}
}
- return rootClass;
+ return mainClass;
}
/**
@@ -1140,7 +1321,7 @@ public final class Context {
private final int size;
private final ReferenceQueue<Class<?>> queue;
- ClassCache(int size) {
+ ClassCache(final int size) {
super(size, 0.75f, true);
this.size = size;
this.queue = new ReferenceQueue<>();
@@ -1156,7 +1337,7 @@ public final class Context {
}
@Override
- public ClassReference get(Object key) {
+ public ClassReference get(final Object key) {
for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
remove(ref.source);
}
@@ -1176,7 +1357,7 @@ public final class Context {
// Class cache management
private Class<?> findCachedClass(final Source source) {
- ClassReference ref = classCache == null ? null : classCache.get(source);
+ final ClassReference ref = classCache == null ? null : classCache.get(source);
return ref != null ? ref.get() : null;
}
@@ -1186,5 +1367,121 @@ public final class Context {
}
}
+ // logging
+ private final Map<String, DebugLogger> loggers = new HashMap<>();
+
+ private void initLoggers() {
+ ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this);
+ }
+
+ /**
+ * Get a logger, given a loggable class
+ * @param clazz a Loggable class
+ * @return debuglogger associated with that class
+ */
+ public DebugLogger getLogger(final Class<? extends Loggable> clazz) {
+ return getLogger(clazz, null);
+ }
+
+ /**
+ * Get a logger, given a loggable class
+ * @param clazz a Loggable class
+ * @param initHook an init hook - if this is the first time the logger is created in the context, run the init hook
+ * @return debuglogger associated with that class
+ */
+ public DebugLogger getLogger(final Class<? extends Loggable> clazz, final Consumer<DebugLogger> initHook) {
+ final String name = getLoggerName(clazz);
+ DebugLogger logger = loggers.get(name);
+ if (logger == null) {
+ if (!env.hasLogger(name)) {
+ return DebugLogger.DISABLED_LOGGER;
+ }
+ final LoggerInfo info = env._loggers.get(name);
+ logger = new DebugLogger(name, info.getLevel(), info.isQuiet());
+ if (initHook != null) {
+ initHook.accept(logger);
+ }
+ loggers.put(name, logger);
+ }
+ return logger;
+ }
+
+ /**
+ * Given a Loggable class, weave debug info info a method handle for that logger.
+ * Level.INFO is used
+ *
+ * @param clazz loggable
+ * @param mh method handle
+ * @param text debug printout to add
+ *
+ * @return instrumented method handle, or null if logger not enabled
+ */
+ public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final MethodHandle mh, final Supplier<String> text) {
+ return addLoggingToHandle(clazz, Level.INFO, mh, Integer.MAX_VALUE, false, text);
+ }
+
+ /**
+ * Given a Loggable class, weave debug info info a method handle for that logger.
+ *
+ * @param clazz loggable
+ * @param level log level
+ * @param mh method handle
+ * @param paramStart first parameter to print
+ * @param printReturnValue should we print the return vaulue?
+ * @param text debug printout to add
+ *
+ * @return instrumented method handle, or null if logger not enabled
+ */
+ public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier<String> text) {
+ final DebugLogger log = getLogger(clazz);
+ if (log.isEnabled()) {
+ return MethodHandleFactory.addDebugPrintout(log, level, mh, paramStart, printReturnValue, text.get());
+ }
+ return mh;
+ }
+
+ private static String getLoggerName(final Class<?> clazz) {
+ Class<?> current = clazz;
+ while (current != null) {
+ final Logger log = current.getAnnotation(Logger.class);
+ if (log != null) {
+ assert !"".equals(log.name());
+ return log.name();
+ }
+ current = current.getSuperclass();
+ }
+ assert false;
+ return null;
+ }
+
+ /**
+ * This is a special kind of switchpoint used to guard builtin
+ * properties and prototypes. In the future it might contain
+ * logic to e.g. multiple switchpoint classes.
+ */
+ public static final class BuiltinSwitchPoint extends SwitchPoint {
+ //empty
+ }
+
+ /**
+ * Create a new builtin switchpoint and return it
+ * @param name key name
+ * @return new builtin switchpoint
+ */
+ public SwitchPoint newBuiltinSwitchPoint(final String name) {
+ assert builtinSwitchPoints.get(name) == null;
+ final SwitchPoint sp = new BuiltinSwitchPoint();
+ builtinSwitchPoints.put(name, sp);
+ return sp;
+ }
+
+ /**
+ * Return the builtin switchpoint for a particular key name
+ * @param name key name
+ * @return builtin switchpoint or null if none
+ */
+ public SwitchPoint getBuiltinSwitchPoint(final String name) {
+ return builtinSwitchPoints.get(name);
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/Debug.java b/src/jdk/nashorn/internal/runtime/Debug.java
index b712f1d0..a2d136fc 100644
--- a/src/jdk/nashorn/internal/runtime/Debug.java
+++ b/src/jdk/nashorn/internal/runtime/Debug.java
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.parser.TokenType.EOF;
-
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenStream;
@@ -41,6 +40,29 @@ public final class Debug {
}
/**
+ * Return the topmost JavaScript frame in a stack trace
+ * @param t throwable that contains the stack trace
+ * @return line describing the topmost JavaScript frame
+ */
+ public static String firstJSFrame(final Throwable t) {
+ for (final StackTraceElement ste : t.getStackTrace()) {
+ if (ECMAErrors.isScriptFrame(ste)) {
+ return ste.toString();
+ }
+ }
+ return "<native code>";
+ }
+
+ /**
+ * Return the topmost JavaScript frame from the current
+ * continuation
+ * @return line describing the topmost JavaScript frame
+ */
+ public static String firstJSFrame() {
+ return firstJSFrame(new Throwable());
+ }
+
+ /**
* Return the system identity hashcode for an object as a human readable
* string
*
@@ -48,7 +70,18 @@ public final class Debug {
* @return system identity hashcode as string
*/
public static String id(final Object x) {
- return "0x" + Integer.toHexString(System.identityHashCode(x));
+ return String.format("0x%08x", System.identityHashCode(x));
+ }
+
+ /**
+ * Same as {@link Debug#id} but returns the identity hashcode as
+ * an integer
+ *
+ * @param x object
+ * @return system identity hashcode
+ */
+ public static int intId(final Object x) {
+ return System.identityHashCode(x);
}
/**
diff --git a/src/jdk/nashorn/internal/runtime/DebugLogger.java b/src/jdk/nashorn/internal/runtime/DebugLogger.java
deleted file mode 100644
index e832c861..00000000
--- a/src/jdk/nashorn/internal/runtime/DebugLogger.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.io.PrintWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import jdk.nashorn.internal.runtime.options.Options;
-
-/**
- * Wrapper class for Logging system. This is how you are supposed to register a logger and use it
- */
-
-public final class DebugLogger {
- private final Logger logger;
- private final boolean isEnabled;
-
- private int indent;
-
- private static final int INDENT_SPACE = 4;
-
- /**
- * Constructor
- *
- * @param loggerName name of logger - this is the unique key with which it can be identified
- */
- public DebugLogger(final String loggerName) {
- this(loggerName, null);
- }
-
- /**
- * Constructor
- *
- * A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log}
- *
- * @param loggerName name of logger - this is the unique key with which it can be identified
- * @param property system property activating the logger on {@code info} level
- */
- public DebugLogger(final String loggerName, final String property) {
- if (property != null && Options.getBooleanProperty(property)) {
- this.logger = Logging.getOrCreateLogger(loggerName, Level.INFO);
- } else {
- this.logger = Logging.getLogger(loggerName);
- }
- assert logger != null;
- this.isEnabled = getLevel() != Level.OFF;
- }
-
- /**
- * Do not currently support chaining this with parent logger. Logger level null
- * means disabled
- * @return level
- */
- private Level getLevel() {
- return logger.getLevel() == null ? Level.OFF : logger.getLevel();
- }
-
- /**
- * Get the output writer for the logger. Loggers always default to
- * stderr for output as they are used mainly to output debug info
- *
- * Can be inherited so this should not be static.
- *
- * @return print writer for log output.
- */
- @SuppressWarnings("static-method")
- public PrintWriter getOutputStream() {
- return Context.getCurrentErr();
- }
-
- /**
- * Check if the logger is enabled
- * @return true if enabled
- */
- public boolean isEnabled() {
- return isEnabled;
- }
-
- /**
- * If you want to change the indent level of your logger, call indent with a new position.
- * Positions start at 0 and are increased by one for a new "tab"
- *
- * @param pos indent position
- */
- public void indent(final int pos) {
- if (isEnabled) {
- indent += pos * INDENT_SPACE;
- }
- }
-
- /**
- * Add an indent position
- */
- public void indent() {
- indent += INDENT_SPACE;
- }
-
- /**
- * Unindent a position
- */
- public void unindent() {
- indent -= INDENT_SPACE;
- if (indent < 0) {
- indent = 0;
- }
- }
-
- /**
- * Check if the logger is above of the level of detail given
- * @see java.util.logging.Level
- *
- * @param level logging level
- * @return true if level is above the given one
- */
- public boolean levelAbove(final Level level) {
- return getLevel().intValue() > level.intValue();
- }
-
- /**
- * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
- * @param str the string to log
- */
- public void finest(final String str) {
- log(Level.FINEST, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINEST} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void finest(final Object... objs) {
- log(Level.FINEST, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINER} on this logger
- * @param str the string to log
- */
- public void finer(final String str) {
- log(Level.FINER, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINER} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void finer(final Object... objs) {
- log(Level.FINER, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINE} on this logger
- * @param str the string to log
- */
- public void fine(final String str) {
- log(Level.FINE, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINE} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void fine(final Object... objs) {
- log(Level.FINE, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#CONFIG} on this logger
- * @param str the string to log
- */
- public void config(final String str) {
- log(Level.CONFIG, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#CONFIG} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void config(final Object... objs) {
- log(Level.CONFIG, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#INFO} on this logger
- * @param str the string to log
- */
- public void info(final String str) {
- log(Level.INFO, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINE} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void info(final Object... objs) {
- log(Level.INFO, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#WARNING} on this logger
- * @param str the string to log
- */
- public void warning(final String str) {
- log(Level.WARNING, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINE} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void warning(final Object... objs) {
- log(Level.WARNING, objs);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#SEVERE} on this logger
- * @param str the string to log
- */
- public void severe(final String str) {
- log(Level.SEVERE, str);
- }
-
- /**
- * Shorthand for outputting a log string as log level
- * {@link java.util.logging.Level#FINE} on this logger
- * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
- */
- public void severe(final Object... objs) {
- log(Level.SEVERE, objs);
- }
-
- /**
- * Output log line on this logger at a given level of verbosity
- * @see java.util.logging.Level
- *
- * @param level minimum log level required for logging to take place
- * @param str string to log
- */
- public void log(final Level level, final String str) {
- if (isEnabled) {
- final StringBuilder sb = new StringBuilder();
- for (int i = 0 ; i < indent ; i++) {
- sb.append(' ');
- }
- sb.append(str);
- logger.log(level, sb.toString());
- }
- }
-
- /**
- * Output log line on this logger at a given level of verbosity
- * @see java.util.logging.Level
- *
- * @param level minimum log level required for logging to take place
- * @param objs objects for which to invoke toString and concatenate to log
- */
- public void log(final Level level, final Object... objs) {
- if (isEnabled) {
- final StringBuilder sb = new StringBuilder();
- for (int i = 0 ; i < indent ; i++) {
- sb.append(' ');
- }
- for (final Object obj : objs) {
- sb.append(obj);
- }
- logger.log(level, sb.toString());
- }
- }
-}
diff --git a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
index 38e5d858..d5dc560f 100644
--- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
+++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
@@ -53,6 +54,7 @@ final class DebuggerSupport {
* available to external debuggers.
*/
@SuppressWarnings("unused")
+ final
DebuggerValueDesc forceLoad = new DebuggerValueDesc(null, false, null, null);
// Hook to force the loading of the SourceInfo class
@@ -155,7 +157,7 @@ final class DebuggerSupport {
try {
return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED, false);
- } catch (Throwable ex) {
+ } catch (final Throwable ex) {
return returnException ? ex : null;
}
}
@@ -237,12 +239,12 @@ final class DebuggerSupport {
if (ScriptObject.isArray(object)) {
sb.append('[');
- final long length = object.getLong("length");
+ final long length = object.getLong("length", INVALID_PROGRAM_POINT);
for (long i = 0; i < length; i++) {
if (object.has(i)) {
final Object valueAsObject = object.get(i);
- final boolean isUndefined = JSType.of(valueAsObject) == JSType.UNDEFINED;
+ final boolean isUndefined = valueAsObject == ScriptRuntime.UNDEFINED;
if (isUndefined) {
if (i != 0) {
diff --git a/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java b/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
index dcceccbc..e69eda92 100644
--- a/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
+++ b/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
@@ -34,63 +34,63 @@ package jdk.nashorn.internal.runtime;
public abstract class DefaultPropertyAccess implements PropertyAccess {
@Override
- public int getInt(final Object key) {
+ public int getInt(final Object key, final int programPoint) {
return JSType.toInt32(get(key));
}
@Override
- public int getInt(final double key) {
- return getInt(JSType.toObject(key));
+ public int getInt(final double key, final int programPoint) {
+ return getInt(JSType.toObject(key), programPoint);
}
@Override
- public int getInt(final long key) {
- return getInt(JSType.toObject(key));
+ public int getInt(final long key, final int programPoint) {
+ return getInt(JSType.toObject(key), programPoint);
}
@Override
- public int getInt(final int key) {
- return getInt(JSType.toObject(key));
+ public int getInt(final int key, final int programPoint) {
+ return getInt(JSType.toObject(key), programPoint);
}
@Override
- public long getLong(final Object key) {
+ public long getLong(final Object key, final int programPoint) {
return JSType.toLong(get(key));
}
@Override
- public long getLong(final double key) {
- return getLong(JSType.toObject(key));
+ public long getLong(final double key, final int programPoint) {
+ return getLong(JSType.toObject(key), programPoint);
}
@Override
- public long getLong(final long key) {
- return getLong(JSType.toObject(key));
+ public long getLong(final long key, final int programPoint) {
+ return getLong(JSType.toObject(key), programPoint);
}
@Override
- public long getLong(final int key) {
- return getLong(JSType.toObject(key));
+ public long getLong(final int key, final int programPoint) {
+ return getLong(JSType.toObject(key), programPoint);
}
@Override
- public double getDouble(final Object key) {
+ public double getDouble(final Object key, final int programPoint) {
return JSType.toNumber(get(key));
}
@Override
- public double getDouble(final double key) {
- return getDouble(JSType.toObject(key));
+ public double getDouble(final double key, final int programPoint) {
+ return getDouble(JSType.toObject(key), programPoint);
}
@Override
- public double getDouble(final long key) {
- return getDouble(JSType.toObject(key));
+ public double getDouble(final long key, final int programPoint) {
+ return getDouble(JSType.toObject(key), programPoint);
}
@Override
- public double getDouble(final int key) {
- return getDouble(JSType.toObject(key));
+ public double getDouble(final int key, final int programPoint) {
+ return getDouble(JSType.toObject(key), programPoint);
}
@Override
@@ -112,82 +112,82 @@ public abstract class DefaultPropertyAccess implements PropertyAccess {
}
@Override
- public void set(final double key, final int value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final double key, final int value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final double key, final long value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final double key, final long value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final double key, final double value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final double key, final double value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final double key, final Object value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final double key, final Object value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final long key, final int value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final long key, final int value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final long key, final long value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final long key, final long value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final long key, final double value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final long key, final double value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final long key, final Object value, final boolean strict) {
- set(JSType.toObject(key), value, strict);
+ public void set(final long key, final Object value, final int flags) {
+ set(JSType.toObject(key), value, flags);
}
@Override
- public void set(final int key, final int value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final int key, final int value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final int key, final long value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final int key, final long value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final int key, final double value, final boolean strict) {
- set(JSType.toObject(key), JSType.toObject(value), strict);
+ public void set(final int key, final double value, final int flags) {
+ set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final int key, final Object value, final boolean strict) {
- set(JSType.toObject(key), value, strict);
+ public void set(final int key, final Object value, final int flags) {
+ set(JSType.toObject(key), value, flags);
}
@Override
- public void set(final Object key, final int value, final boolean strict) {
- set(key, JSType.toObject(value), strict);
+ public void set(final Object key, final int value, final int flags) {
+ set(key, JSType.toObject(value), flags);
}
@Override
- public void set(final Object key, final long value, final boolean strict) {
- set(key, JSType.toObject(value), strict);
+ public void set(final Object key, final long value, final int flags) {
+ set(key, JSType.toObject(value), flags);
}
@Override
- public void set(final Object key, final double value, final boolean strict) {
- set(key, JSType.toObject(value), strict);
+ public void set(final Object key, final double value, final int flags) {
+ set(key, JSType.toObject(value), flags);
}
@Override
- public abstract void set(Object key, Object value, boolean strict);
+ public abstract void set(Object key, Object value, int flags);
@Override
public abstract boolean has(Object key);
diff --git a/src/jdk/nashorn/internal/runtime/ECMAErrors.java b/src/jdk/nashorn/internal/runtime/ECMAErrors.java
index affba497..9dbd6423 100644
--- a/src/jdk/nashorn/internal/runtime/ECMAErrors.java
+++ b/src/jdk/nashorn/internal/runtime/ECMAErrors.java
@@ -28,10 +28,9 @@ package jdk.nashorn.internal.runtime;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
-import jdk.nashorn.api.scripting.NashornException;
-import jdk.nashorn.internal.scripts.JS;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.scripts.JS;
/**
* Helper class to throw various standard "ECMA error" exceptions such as Error, ReferenceError, TypeError etc.
@@ -47,7 +46,7 @@ public final class ECMAErrors {
/** We assume that compiler generates script classes into the known package. */
private static final String scriptPackage;
static {
- String name = JS.class.getName();
+ final String name = JS.class.getName();
scriptPackage = name.substring(0, name.lastIndexOf('.'));
}
@@ -403,14 +402,10 @@ public final class ECMAErrors {
final String className = frame.getClassName();
// Look for script package in class name (into which compiler puts generated code)
- if (className.startsWith(scriptPackage) && !frame.getMethodName().startsWith(CompilerConstants.INTERNAL_METHOD_PREFIX)) {
+ if (className.startsWith(scriptPackage) && !CompilerConstants.isInternalMethodName(frame.getMethodName())) {
final String source = frame.getFileName();
- /*
- * Make sure that it is not some Java code that Nashorn has in that package!
- * also, we don't want to report JavaScript code that lives in script engine implementation
- * We want to report only user's own scripts and not any of our own scripts like "engine.js"
- */
- return source != null && !source.endsWith(".java") && !source.contains(NashornException.ENGINE_SCRIPT_SOURCE_NAME);
+ // Make sure that it is not some Java code that Nashorn has in that package!
+ return source != null && !source.endsWith(".java");
}
return false;
}
diff --git a/src/jdk/nashorn/internal/runtime/ECMAException.java b/src/jdk/nashorn/internal/runtime/ECMAException.java
index c900963d..f906e18f 100644
--- a/src/jdk/nashorn/internal/runtime/ECMAException.java
+++ b/src/jdk/nashorn/internal/runtime/ECMAException.java
@@ -96,15 +96,17 @@ public final class ECMAException extends NashornException {
// If thrown object is an Error or sub-object like TypeError, then
// an ECMAException object has been already initialized at constructor.
if (thrown instanceof ScriptObject) {
- ScriptObject sobj = (ScriptObject)thrown;
- Object exception = getException(sobj);
+ final Object exception = getException((ScriptObject)thrown);
if (exception instanceof ECMAException) {
- // copy over file name, line number and column number.
final ECMAException ee = (ECMAException)exception;
- ee.setFileName(fileName);
- ee.setLineNumber(line);
- ee.setColumnNumber(column);
- return ee;
+ // Make sure exception has correct thrown reference because that's what will end up getting caught.
+ if (ee.getThrown() == thrown) {
+ // copy over file name, line number and column number.
+ ee.setFileName(fileName);
+ ee.setLineNumber(line);
+ ee.setColumnNumber(column);
+ return ee;
+ }
}
}
@@ -154,7 +156,11 @@ public final class ECMAException extends NashornException {
* @return a {@link ECMAException}
*/
public static Object getException(final ScriptObject errObj) {
- return errObj.get(ECMAException.EXCEPTION_PROPERTY);
+ // Exclude inherited properties that may belong to errors in the prototype chain.
+ if (errObj.hasOwnProperty(ECMAException.EXCEPTION_PROPERTY)) {
+ return errObj.get(ECMAException.EXCEPTION_PROPERTY);
+ }
+ return null;
}
/**
@@ -285,7 +291,7 @@ public final class ECMAException extends NashornException {
if (!sobj.has(EXCEPTION_PROPERTY)) {
sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
} else {
- sobj.set(EXCEPTION_PROPERTY, this, false);
+ sobj.set(EXCEPTION_PROPERTY, this, 0);
}
}
}
diff --git a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index f16cf41c..c868aab2 100644
--- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.List;
/**
* This is a subclass that represents a script function that may not be regenerated.
@@ -35,6 +35,8 @@ import java.lang.invoke.MethodHandle;
*/
final class FinalScriptFunctionData extends ScriptFunctionData {
+ private static final long serialVersionUID = -930632846167768864L;
+
/**
* Constructor - used for bind
*
@@ -43,9 +45,10 @@ final class FinalScriptFunctionData extends ScriptFunctionData {
* @param functions precompiled code
* @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, final int arity, final CompiledFunctions functions, final int flags) {
+ FinalScriptFunctionData(final String name, final int arity, final List<CompiledFunction> functions, final int flags) {
super(name, arity, flags);
code.addAll(functions);
+ assert !needsCallee();
}
/**
@@ -57,33 +60,84 @@ final class FinalScriptFunctionData extends ScriptFunctionData {
* @param specs specializations
* @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) {
- super(name, arity(mh), flags);
+ FinalScriptFunctionData(final String name, final MethodHandle mh, final Specialization[] specs, final int flags) {
+ super(name, methodHandleArity(mh), flags);
addInvoker(mh);
if (specs != null) {
- for (final MethodHandle spec : specs) {
- addInvoker(spec);
+ for (final Specialization spec : specs) {
+ addInvoker(spec.getMethodHandle(), spec);
+ }
+ }
+ }
+
+ @Override
+ boolean isRecompilable() {
+ return false;
+ }
+
+ @Override
+ protected boolean needsCallee() {
+ final boolean needsCallee = code.getFirst().needsCallee();
+ assert allNeedCallee(needsCallee);
+ return needsCallee;
+ }
+
+ private boolean allNeedCallee(final boolean needCallee) {
+ for (final CompiledFunction inv : code) {
+ if(inv.needsCallee() != needCallee) {
+ return false;
}
}
+ return true;
}
- private void addInvoker(final MethodHandle mh) {
+ @Override
+ MethodType getGenericType() {
+ // We need to ask the code for its generic type. We can't just rely on this function data's arity, as it's not
+ // actually correct for lots of built-ins. E.g. ECMAScript 5.1 section 15.5.3.2 prescribes that
+ // Script.fromCharCode([char0[, char1[, ...]]]) has a declared arity of 1 even though it's a variable arity
+ // method.
+ int max = 0;
+ for(final CompiledFunction fn: code) {
+ final MethodType t = fn.type();
+ if(ScriptFunctionData.isVarArg(t)) {
+ // 2 for (callee, this, args[])
+ return MethodType.genericMethodType(2, true);
+ }
+ final int paramCount = t.parameterCount() - (ScriptFunctionData.needsCallee(t) ? 1 : 0);
+ if(paramCount > max) {
+ max = paramCount;
+ }
+ }
+ // +1 for callee
+ return MethodType.genericMethodType(max + 1);
+ }
+
+ private CompiledFunction addInvoker(final MethodHandle mh, final Specialization specialization) {
+ assert !needsCallee(mh);
+
+ final CompiledFunction invoker;
if (isConstructor(mh)) {
// only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor
// is too conservative a check. However, isConstructor(mh) always implies isConstructor param
assert isConstructor();
- final MethodHandle invoker = MH.insertArguments(mh, 0, false);
- final MethodHandle constructor = composeConstructor(MH.insertArguments(mh, 0, true));
- code.add(new CompiledFunction(mh.type(), invoker, constructor));
+ invoker = CompiledFunction.createBuiltInConstructor(mh);
} else {
- code.add(new CompiledFunction(mh.type(), mh));
+ invoker = new CompiledFunction(mh, null, specialization);
}
+ code.add(invoker);
+
+ return invoker;
+ }
+
+ private CompiledFunction addInvoker(final MethodHandle mh) {
+ return addInvoker(mh, null);
}
- private static int arity(final MethodHandle mh) {
+ private static int methodHandleArity(final MethodHandle mh) {
if (isVarArg(mh)) {
- return -1;
+ return MAX_ARITY;
}
//drop self, callee and boolean constructor flag to get real arity
diff --git a/src/jdk/nashorn/internal/runtime/FindProperty.java b/src/jdk/nashorn/internal/runtime/FindProperty.java
index 87a8c748..3b153c58 100644
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java
+++ b/src/jdk/nashorn/internal/runtime/FindProperty.java
@@ -26,9 +26,12 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import java.lang.invoke.MethodHandle;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
/**
* This class represents the result from a find property search.
@@ -57,19 +60,43 @@ public final class FindProperty {
}
/**
+ * Return a copy of this FindProperty with a different property.
+ *
+ * @param newProperty the new property
+ * @return the new FindProperty instance
+ */
+ public FindProperty replaceProperty(final Property newProperty) {
+ assert this.property.getKey().equals(newProperty.getKey());
+ assert this.property.getSlot() == newProperty.getSlot();
+ return new FindProperty(self, prototype, newProperty);
+ }
+
+ /**
* Ask for a getter that returns the given type. The type has nothing to do with the
* internal representation of the property. It may be an Object (boxing primitives) or
* a primitive (primitive fields with -Dnashorn.fields.dual=true)
* @see ObjectClassGenerator
*
* @param type type of getter, e.g. int.class if we want a function with {@code get()I} signature
+ * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic
+ * @param request link request
+ *
* @return method handle for the getter
*/
- public MethodHandle getGetter(final Class<?> type) {
- MethodHandle getter = property.getGetter(type);
+ public MethodHandle getGetter(final Class<?> type, final int programPoint, final LinkRequest request) {
+ MethodHandle getter;
+ if (isValid(programPoint)) {
+ getter = property.getOptimisticGetter(type, programPoint);
+ } else {
+ getter = property.getGetter(type);
+ }
if (property instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty)property;
- getter = MH.insertArguments(getter, 0, isInherited() ? getOwner() : null, uc.getGetterSlot());
+ getter = MH.insertArguments(getter, 1, UserAccessorProperty.getINVOKE_UA_GETTER(type, programPoint));
+ if (isValid(programPoint) && type.isPrimitive()) {
+ getter = MH.insertArguments(getter, 1, programPoint);
+ }
+ property.setType(type);
+ return insertAccessorsGetter((UserAccessorProperty) property, request, getter);
}
return getter;
}
@@ -82,20 +109,36 @@ public final class FindProperty {
*
* @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature
* @param strict are we in strict mode
+ * @param request link request
*
* @return method handle for the getter
*/
- public MethodHandle getSetter(final Class<?> type, final boolean strict) {
+ public MethodHandle getSetter(final Class<?> type, final boolean strict, final LinkRequest request) {
MethodHandle setter = property.getSetter(type, getOwner().getMap());
if (property instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty) property;
- setter = MH.insertArguments(setter, 0, isInherited() ? getOwner() : null,
- uc.getSetterSlot(), strict? property.getKey() : null);
+ setter = MH.insertArguments(setter, 1, UserAccessorProperty.getINVOKE_UA_SETTER(type), strict ? property.getKey() : null);
+ property.setType(type);
+ return insertAccessorsGetter((UserAccessorProperty) property, request, setter);
}
return setter;
}
+ // Fold an accessor getter into the method handle of a user accessor property.
+ private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) {
+ MethodHandle superGetter = uap.getAccessorsGetter();
+ if (isInherited()) {
+ superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength());
+ }
+ if (request != null && !(request.getReceiver() instanceof ScriptObject)) {
+ final MethodHandle wrapFilter = Global.getPrimitiveWrapFilter(request.getReceiver());
+ superGetter = MH.filterArguments(superGetter, 0, wrapFilter.asType(wrapFilter.type().changeReturnType(superGetter.type().parameterType(0))));
+ }
+ superGetter = MH.asType(superGetter, superGetter.type().changeParameterType(0, Object.class));
+
+ return MH.foldArguments(mh, superGetter);
+ }
+
/**
* Return the {@code ScriptObject} owning of the property: this means the prototype.
* @return owner of property
@@ -105,11 +148,22 @@ public final class FindProperty {
}
/**
+ * Return the {@code ScriptObject} where the search started. This is usually the ScriptObject the
+ * operation was started on, except for properties found inside a 'with' statement, where it is the
+ * top-level 'with' expression object.
+ *
+ * @return the start object.
+ */
+ public ScriptObject getSelf() {
+ return self;
+ }
+
+ /**
* Return the appropriate receiver for a getter.
* @return appropriate receiver
*/
public ScriptObject getGetterReceiver() {
- return property != null && property.hasGetterFunction(prototype) ? self : prototype;
+ return property != null && property instanceof UserAccessorProperty ? self : prototype;
}
/**
@@ -155,7 +209,27 @@ public final class FindProperty {
/**
* Get the property value from self as object.
- *
+ * @return the property value
+ */
+ public int getIntValue() {
+ return property.getIntValue(getGetterReceiver(), getOwner());
+ }
+ /**
+ * Get the property value from self as object.
+ * @return the property value
+ */
+ public long getLongValue() {
+ return property.getLongValue(getGetterReceiver(), getOwner());
+ }
+ /**
+ * Get the property value from self as object.
+ * @return the property value
+ */
+ public double getDoubleValue() {
+ return property.getDoubleValue(getGetterReceiver(), getOwner());
+ }
+ /**
+ * Get the property value from self as object.
* @return the property value
*/
public Object getObjectValue() {
@@ -168,8 +242,38 @@ public final class FindProperty {
* @param value the new value
* @param strict strict flag
*/
- public void setObjectValue(final Object value, final boolean strict) {
- property.setObjectValue(getSetterReceiver(), getOwner(), value, strict);
+ public void setValue(final int value, final boolean strict) {
+ property.setValue(getSetterReceiver(), getOwner(), value, strict);
+ }
+
+ /**
+ * Set the property value in self.
+ *
+ * @param value the new value
+ * @param strict strict flag
+ */
+ public void setValue(final long value, final boolean strict) {
+ property.setValue(getSetterReceiver(), getOwner(), value, strict);
+ }
+
+ /**
+ * Set the property value in self.
+ *
+ * @param value the new value
+ * @param strict strict flag
+ */
+ public void setValue(final double value, final boolean strict) {
+ property.setValue(getSetterReceiver(), getOwner(), value, strict);
+ }
+
+ /**
+ * Set the property value in self.
+ *
+ * @param value the new value
+ * @param strict strict flag
+ */
+ public void setValue(final Object value, final boolean strict) {
+ property.setValue(getSetterReceiver(), getOwner(), value, strict);
}
/**
@@ -187,5 +291,10 @@ public final class FindProperty {
return length;
}
+ @Override
+ public String toString() {
+ return "[FindProperty: " + property.getKey() + ']';
+ }
+
}
diff --git a/src/jdk/nashorn/internal/runtime/FunctionInitializer.java b/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
new file mode 100644
index 00000000..906024d7
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.invoke.MethodType;
+import java.util.Map;
+import jdk.nashorn.internal.codegen.CompileUnit;
+import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+
+/**
+ * Class that contains information allowing us to look up a method handle implementing a JavaScript function
+ * from a generated class. This is used both for code coming from codegen and for persistent serialized code.
+ */
+public final class FunctionInitializer implements Serializable {
+
+ private final String className;
+ private final MethodType methodType;
+ private final int flags;
+ private transient Map<Integer, Type> invalidatedProgramPoints;
+ private transient Class<?> code;
+
+ private static final long serialVersionUID = -5420835725902966692L;
+
+ /**
+ * Constructor.
+ *
+ * @param functionNode the function node
+ */
+ public FunctionInitializer(final FunctionNode functionNode) {
+ this(functionNode, null);
+ }
+
+ /**
+ * Copy constructor.
+ *
+ * @param init original initializer
+ */
+ FunctionInitializer(final FunctionInitializer init) {
+ this.className = init.getClassName();
+ this.methodType = init.getMethodType();
+ this.flags = init.getFlags();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param functionNode the function node
+ * @param invalidatedProgramPoints invalidated program points
+ */
+ public FunctionInitializer(final FunctionNode functionNode, final Map<Integer, Type> invalidatedProgramPoints) {
+ this.className = functionNode.getCompileUnit().getUnitClassName();
+ this.methodType = new FunctionSignature(functionNode).getMethodType();
+ this.flags = functionNode.getFlags();
+ this.invalidatedProgramPoints = invalidatedProgramPoints;
+
+ final CompileUnit cu = functionNode.getCompileUnit();
+ if (cu != null) {
+ this.code = cu.getCode();
+ }
+
+ assert className != null;
+ }
+
+ /**
+ * Returns the name of the class implementing the function.
+ *
+ * @return the class name
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns the type of the method implementing the function.
+ *
+ * @return the method type
+ */
+ public MethodType getMethodType() {
+ return methodType;
+ }
+
+ /**
+ * Returns the function flags.
+ *
+ * @return function flags
+ */
+ public int getFlags() {
+ return flags;
+ }
+
+ /**
+ * Returns the class implementing the function.
+ *
+ * @return the class
+ */
+ public Class<?> getCode() {
+ return code;
+ }
+
+ /**
+ * Set the class implementing the function
+ * @param code the class
+ */
+ public void setCode(final Class<?> code) {
+ // Make sure code has not been set and has expected class name
+ if (this.code != null) {
+ throw new IllegalStateException("code already set");
+ }
+ assert className.equals(code.getTypeName().replace('.', '/')) : "unexpected class name";
+ this.code = code;
+ }
+
+ /**
+ * Returns the map of invalidated program points.
+ *
+ * @return invalidated program points
+ */
+ public Map<Integer, Type> getInvalidatedProgramPoints() {
+ return invalidatedProgramPoints;
+ }
+
+ private void writeObject(final ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ Type.writeTypeMap(invalidatedProgramPoints, out);
+ }
+
+ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ invalidatedProgramPoints = Type.readTypeMap(in);
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/FunctionScope.java b/src/jdk/nashorn/internal/runtime/FunctionScope.java
index b3872c45..133c64f0 100644
--- a/src/jdk/nashorn/internal/runtime/FunctionScope.java
+++ b/src/jdk/nashorn/internal/runtime/FunctionScope.java
@@ -72,6 +72,19 @@ public class FunctionScope extends ScriptObject implements Scope {
}
/**
+ * Constructor
+ *
+ * @param map property map
+ * @param primitiveSpill primitive spill pool
+ * @param objectSpill reference spill pool
+ */
+ public FunctionScope(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+ super(map, primitiveSpill, objectSpill);
+ this.arguments = null;
+ }
+
+
+ /**
* Get the current split state.
* @return current split state
*/
diff --git a/src/jdk/nashorn/internal/runtime/GlobalConstants.java b/src/jdk/nashorn/internal/runtime/GlobalConstants.java
new file mode 100644
index 00000000..cd1061c2
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.SwitchPoint;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.DynamicLinker;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Each context owns one of these. This is basically table of accessors
+ * for global properties. A global constant is evaluated to a MethodHandle.constant
+ * for faster access and to avoid walking to proto chain looking for it.
+ *
+ * We put a switchpoint on the global setter, which invalidates the
+ * method handle constant getters, and reverts to the standard access strategy
+ *
+ * However, there is a twist - while certain globals like "undefined" and "Math"
+ * are usually never reassigned, a global value can be reset once, and never again.
+ * This is a rather common pattern, like:
+ *
+ * x = function(something) { ...
+ *
+ * Thus everything registered as a global constant gets an extra chance. Set once,
+ * reregister the switchpoint. Set twice or more - don't try again forever, or we'd
+ * just end up relinking our way into megamorphisism.
+ *
+ * Also it has to be noted that this kind of linking creates a coupling between a Global
+ * and the call sites in compiled code belonging to the Context. For this reason, the
+ * linkage becomes incorrect as soon as the Context has more than one Global. The
+ * {@link #invalidateForever()} is invoked by the Context to invalidate all linkages and
+ * turn off the functionality of this object as soon as the Context's {@link Context#newGlobal()} is invoked
+ * for second time.
+ *
+ * We can extend this to ScriptObjects in general (GLOBAL_ONLY=false), which requires
+ * a receiver guard on the constant getter, but it currently leaks memory and its benefits
+ * have not yet been investigated property.
+ *
+ * As long as all Globals in a Context share the same GlobalConstants instance, we need synchronization
+ * whenever we access it.
+ */
+@Logger(name="const")
+public final class GlobalConstants implements Loggable {
+
+ /**
+ * Should we only try to link globals as constants, and not generic script objects.
+ * Script objects require a receiver guard, which is memory intensive, so this is currently
+ * disabled. We might implement a weak reference based approach to this later.
+ */
+ public static final boolean GLOBAL_ONLY = true;
+
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ private static final MethodHandle INVALIDATE_SP = virtualCall(LOOKUP, GlobalConstants.class, "invalidateSwitchPoint", Object.class, Object.class, Access.class).methodHandle();
+ private static final MethodHandle RECEIVER_GUARD = staticCall(LOOKUP, GlobalConstants.class, "receiverGuard", boolean.class, Access.class, Object.class, Object.class).methodHandle();
+
+ /** Logger for constant getters */
+ private final DebugLogger log;
+
+ /**
+ * Access map for this global - associates a symbol name with an Access object, with getter
+ * and invalidation information
+ */
+ private final Map<String, Access> map = new HashMap<>();
+
+ private final AtomicBoolean invalidatedForever = new AtomicBoolean(false);
+
+ /**
+ * Constructor - used only by global
+ * @param log logger, or null if none
+ */
+ public GlobalConstants(final DebugLogger log) {
+ this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return DebugLogger.DISABLED_LOGGER;
+ }
+
+ /**
+ * Information about a constant access and its potential invalidations
+ */
+ private static class Access {
+ /** name of symbol */
+ private final String name;
+
+ /** switchpoint that invalidates the getters and setters for this access */
+ private SwitchPoint sp;
+
+ /** invalidation count for this access, i.e. how many times has this property been reset */
+ private int invalidations;
+
+ /** has a guard guarding this property getter failed? */
+ private boolean guardFailed;
+
+ private static final int MAX_RETRIES = 2;
+
+ private Access(final String name, final SwitchPoint sp) {
+ this.name = name;
+ this.sp = sp;
+ }
+
+ private boolean hasBeenInvalidated() {
+ return sp.hasBeenInvalidated();
+ }
+
+ private boolean guardFailed() {
+ return guardFailed;
+ }
+
+ private void failGuard() {
+ invalidateOnce();
+ guardFailed = true;
+ }
+
+ private void newSwitchPoint() {
+ assert hasBeenInvalidated();
+ sp = new SwitchPoint();
+ }
+
+ private void invalidate(final int count) {
+ if (!sp.hasBeenInvalidated()) {
+ SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+ invalidations += count;
+ }
+ }
+
+ /**
+ * Invalidate the access, but do not contribute to the invalidation count
+ */
+ private void invalidateUncounted() {
+ invalidate(0);
+ }
+
+ /**
+ * Invalidate the access, and contribute 1 to the invalidation count
+ */
+ private void invalidateOnce() {
+ invalidate(1);
+ }
+
+ /**
+ * Invalidate the access and make sure that we never try to turn this into
+ * a MethodHandle.constant getter again
+ */
+ private void invalidateForever() {
+ invalidate(MAX_RETRIES);
+ }
+
+ /**
+ * Are we allowed to relink this as constant getter, even though it
+ * it has been reset
+ * @return true if we can relink as constant, one retry is allowed
+ */
+ private boolean mayRetry() {
+ return invalidations < MAX_RETRIES;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + quote(name) + " <id=" + Debug.id(this) + "> inv#=" + invalidations + '/' + MAX_RETRIES + " sp_inv=" + sp.hasBeenInvalidated() + ']';
+ }
+
+ String getName() {
+ return name;
+ }
+
+ SwitchPoint getSwitchPoint() {
+ return sp;
+ }
+ }
+
+ /**
+ * To avoid an expensive global guard "is this the same global", similar to the
+ * receiver guard on the ScriptObject level, we invalidate all getters once
+ * when we switch globals. This is used from the class cache. We _can_ reuse
+ * the same class for a new global, but the builtins and global scoped variables
+ * will have changed.
+ */
+ public void invalidateAll() {
+ if (!invalidatedForever.get()) {
+ log.info("New global created - invalidating all constant callsites without increasing invocation count.");
+ synchronized (this) {
+ for (final Access acc : map.values()) {
+ acc.invalidateUncounted();
+ }
+ }
+ }
+ }
+
+ /**
+ * To avoid an expensive global guard "is this the same global", similar to the
+ * receiver guard on the ScriptObject level, we invalidate all getters when the
+ * second Global is created by the Context owning this instance. After this
+ * method is invoked, this GlobalConstants instance will both invalidate all the
+ * switch points it produced, and it will stop handing out new method handles
+ * altogether.
+ */
+ public void invalidateForever() {
+ if (invalidatedForever.compareAndSet(false, true)) {
+ log.info("New global created - invalidating all constant callsites.");
+ synchronized (this) {
+ for (final Access acc : map.values()) {
+ acc.invalidateForever();
+ }
+ map.clear();
+ }
+ }
+ }
+
+ /**
+ * Invalidate the switchpoint of an access - we have written to
+ * the property
+ *
+ * @param obj receiver
+ * @param acc access
+ *
+ * @return receiver, so this can be used as param filter
+ */
+ @SuppressWarnings("unused")
+ private synchronized Object invalidateSwitchPoint(final Object obj, final Access acc) {
+ if (log.isEnabled()) {
+ log.info("*** Invalidating switchpoint " + acc.getSwitchPoint() + " for receiver=" + obj + " access=" + acc);
+ }
+ acc.invalidateOnce();
+ if (acc.mayRetry()) {
+ if (log.isEnabled()) {
+ log.info("Retry is allowed for " + acc + "... Creating a new switchpoint.");
+ }
+ acc.newSwitchPoint();
+ } else {
+ if (log.isEnabled()) {
+ log.info("This was the last time I allowed " + quote(acc.getName()) + " to relink as constant.");
+ }
+ }
+ return obj;
+ }
+
+ private Access getOrCreateSwitchPoint(final String name) {
+ Access acc = map.get(name);
+ if (acc != null) {
+ return acc;
+ }
+ final SwitchPoint sp = new SwitchPoint();
+ map.put(name, acc = new Access(name, sp));
+ return acc;
+ }
+
+ /**
+ * Called from script object on property deletion to erase a property
+ * that might be linked as MethodHandle.constant and force relink
+ * @param name name of property
+ */
+ void delete(final String name) {
+ if (!invalidatedForever.get()) {
+ synchronized (this) {
+ final Access acc = map.get(name);
+ if (acc != null) {
+ acc.invalidateForever();
+ }
+ }
+ }
+ }
+
+ /**
+ * Receiver guard is used if we extend the global constants to script objects in general.
+ * As the property can have different values in different script objects, while Global is
+ * by definition a singleton, we need this for ScriptObject constants (currently disabled)
+ *
+ * TODO: Note - this seems to cause memory leaks. Use weak references? But what is leaking seems
+ * to be the Access objects, which isn't the case for Globals. Weird.
+ *
+ * @param acc access
+ * @param boundReceiver the receiver bound to the callsite
+ * @param receiver the receiver to check against
+ *
+ * @return true if this receiver is still the one we bound to the callsite
+ */
+ @SuppressWarnings("unused")
+ private static boolean receiverGuard(final Access acc, final Object boundReceiver, final Object receiver) {
+ final boolean id = receiver == boundReceiver;
+ if (!id) {
+ acc.failGuard();
+ }
+ return id;
+ }
+
+ private static boolean isGlobalSetter(final ScriptObject receiver, final FindProperty find) {
+ if (find == null) {
+ return receiver.isScope();
+ }
+ return find.getOwner().isGlobal();
+ }
+
+ /**
+ * Augment a setter with switchpoint for invalidating its getters, should the setter be called
+ *
+ * @param find property lookup
+ * @param inv normal guarded invocation for this setter, as computed by the ScriptObject linker
+ * @param desc callsite descriptor
+ * @param request link request
+ *
+ * @return null if failed to set up constant linkage
+ */
+ GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
+ if (invalidatedForever.get() || (GLOBAL_ONLY && !isGlobalSetter(receiver, find))) {
+ return null;
+ }
+
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
+ synchronized (this) {
+ final Access acc = getOrCreateSwitchPoint(name);
+
+ if (log.isEnabled()) {
+ log.fine("Trying to link constant SETTER ", acc);
+ }
+
+ if (!acc.mayRetry() || invalidatedForever.get()) {
+ if (log.isEnabled()) {
+ log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
+ }
+ return null;
+ }
+
+ if (acc.hasBeenInvalidated()) {
+ log.info("New chance for " + acc);
+ acc.newSwitchPoint();
+ }
+
+ assert !acc.hasBeenInvalidated();
+
+ // if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter
+ final MethodHandle target = inv.getInvocation();
+ final Class<?> receiverType = target.type().parameterType(0);
+ final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this);
+ final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
+ final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
+
+ assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints());
+ log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
+ return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException());
+ }
+ }
+
+ /**
+ * Try to reuse constant method handles for getters
+ * @param c constant value
+ * @return method handle (with dummy receiver) that returns this constant
+ */
+ public static MethodHandle staticConstantGetter(final Object c) {
+ return MH.dropArguments(JSType.unboxConstant(c), 0, Object.class);
+ }
+
+ private MethodHandle constantGetter(final Object c) {
+ final MethodHandle mh = staticConstantGetter(c);
+ if (log.isEnabled()) {
+ return MethodHandleFactory.addDebugPrintout(log, Level.FINEST, mh, "getting as constant");
+ }
+ return mh;
+ }
+
+ /**
+ * Try to turn a getter into a MethodHandle.constant, if possible
+ *
+ * @param find property lookup
+ * @param receiver receiver
+ * @param desc callsite descriptor
+ *
+ * @return resulting getter, or null if failed to create constant
+ */
+ GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
+ // Only use constant getter for fast scope access, because the receiver may change between invocations
+ // for slow-scope and non-scope callsites.
+ // Also return null for user accessor properties as they may have side effects.
+ if (invalidatedForever.get() || !NashornCallSiteDescriptor.isFastScope(desc)
+ || (GLOBAL_ONLY && !find.getOwner().isGlobal())
+ || find.getProperty() instanceof UserAccessorProperty) {
+ return null;
+ }
+
+ final boolean isOptimistic = NashornCallSiteDescriptor.isOptimistic(desc);
+ final int programPoint = isOptimistic ? getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+ final Class<?> retType = desc.getMethodType().returnType();
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
+ synchronized (this) {
+ final Access acc = getOrCreateSwitchPoint(name);
+
+ log.fine("Starting to look up object value " + name);
+ final Object c = find.getObjectValue();
+
+ if (log.isEnabled()) {
+ log.fine("Trying to link constant GETTER " + acc + " value = " + c);
+ }
+
+ if (acc.hasBeenInvalidated() || acc.guardFailed() || invalidatedForever.get()) {
+ if (log.isEnabled()) {
+ log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
+ }
+ return null;
+ }
+
+ final MethodHandle cmh = constantGetter(c);
+
+ MethodHandle mh;
+ MethodHandle guard;
+
+ if (isOptimistic) {
+ if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) {
+ //widen return type - this is pessimistic, so it will always work
+ mh = MH.asType(cmh, cmh.type().changeReturnType(retType));
+ } else {
+ //immediately invalidate - we asked for a too wide constant as a narrower one
+ mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class);
+ }
+ } else {
+ //pessimistic return type filter
+ mh = Lookup.filterReturnType(cmh, retType);
+ }
+
+ if (find.getOwner().isGlobal()) {
+ guard = null;
+ } else {
+ guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver);
+ }
+
+ if (log.isEnabled()) {
+ log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
+ mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc);
+ }
+
+ return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null);
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
index 10747a1b..c7094adc 100644
--- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
@@ -25,7 +25,6 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.JSType.digit;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
@@ -38,11 +37,35 @@ import java.util.Locale;
public final class GlobalFunctions {
/** Methodhandle to implementation of ECMA 15.1.2.2, parseInt */
- public static final MethodHandle PARSEINT = findOwnMH("parseInt", double.class, Object.class, Object.class, Object.class);
+ public static final MethodHandle PARSEINT = findOwnMH("parseInt", double.class, Object.class, Object.class, Object.class);
+
+ /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */
+ public static final MethodHandle PARSEINT_OI = findOwnMH("parseInt", double.class, Object.class, Object.class, int.class);
+
+ /** ParseInt - NaN for booleans (thru string conversion to number conversion) */
+ public static final MethodHandle PARSEINT_Z = MH.dropArguments(MH.dropArguments(MH.constant(double.class, Double.NaN), 0, boolean.class), 0, Object.class);
+
+ /** ParseInt - identity for ints */
+ public static final MethodHandle PARSEINT_I = MH.dropArguments(MH.identity(int.class), 0, Object.class);
+
+ /** ParseInt - identity for longs */
+ public static final MethodHandle PARSEINT_J = MH.dropArguments(MH.identity(long.class), 0, Object.class);
+
+ /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */
+ public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class);
/** Methodhandle to implementation of ECMA 15.1.2.3, parseFloat */
public static final MethodHandle PARSEFLOAT = findOwnMH("parseFloat", double.class, Object.class, Object.class);
+ /** isNan for integers - always false */
+ public static final MethodHandle IS_NAN_I = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class);
+
+ /** isNan for longs - always false */
+ public static final MethodHandle IS_NAN_J = MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class);
+
+ /** IsNan for doubles - use Double.isNaN */
+ public static final MethodHandle IS_NAN_D = MH.dropArguments(MH.findStatic(MethodHandles.lookup(), Double.class, "isNaN", MH.type(boolean.class, double.class)), 0, Object.class);
+
/** Methodhandle to implementation of ECMA 15.1.2.4, isNaN */
public static final MethodHandle IS_NAN = findOwnMH("isNaN", boolean.class, Object.class, Object.class);
@@ -78,19 +101,44 @@ public final class GlobalFunctions {
/**
* ECMA 15.1.2.2 parseInt implementation
*
- * TODO: specialize
- *
* @param self self reference
* @param string string to parse
* @param rad radix
*
- * @return numeric type representing string contents as an int (TODO: specialize for int case)
+ * @return numeric type representing string contents as an int
*/
- //TODO specialize
public static double parseInt(final Object self, final Object string, final Object rad) {
- final String str = JSType.trimLeft(JSType.toString(string));
- final int length = str.length();
- int radix = JSType.toInt32(rad);
+ return parseIntInternal(JSType.trimLeft(JSType.toString(string)), JSType.toInt32(rad));
+ }
+
+ /**
+ * ECMA 15.1.2.2 parseInt implementation specialized for int radix
+ *
+ * @param self self reference
+ * @param string string to parse
+ * @param rad radix
+ *
+ * @return numeric type representing string contents as an int
+ */
+ public static double parseInt(final Object self, final Object string, final int rad) {
+ return parseIntInternal(JSType.trimLeft(JSType.toString(string)), rad);
+ }
+
+ /**
+ * ECMA 15.1.2.2 parseInt implementation specialized for no radix argument
+ *
+ * @param self self reference
+ * @param string string to parse
+ *
+ * @return numeric type representing string contents as an int
+ */
+ public static double parseInt(final Object self, final Object string) {
+ return parseIntInternal(JSType.trimLeft(JSType.toString(string)), 0);
+ }
+
+ private static double parseIntInternal(final String str, final int rad) {
+ final int length = str.length();
+ int radix = rad;
// empty string is not valid
if (length == 0) {
@@ -142,7 +190,7 @@ public final class GlobalFunctions {
// we should see atleast one valid digit
boolean entered = false;
while (idx < length) {
- digit = digit(str.charAt(idx++), radix, true);
+ digit = fastDigit(str.charAt(idx++), radix);
if (digit < 0) {
break;
}
@@ -456,6 +504,20 @@ loop:
return ScriptRuntime.UNDEFINED;
}
+ private static int fastDigit(final int ch, final int radix) {
+ int n = -1;
+ if (ch >= '0' && ch <= '9') {
+ n = ch - '0';
+ } else if (radix > 10) {
+ if (ch >= 'a' && ch <= 'z') {
+ n = ch - 'a' + 10;
+ } else if (ch >= 'A' && ch <= 'Z') {
+ n = ch - 'A' + 10;
+ }
+ }
+ return n < radix ? n : -1;
+ }
+
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), GlobalFunctions.class, name, MH.type(rtype, types));
}
diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index ab1de42f..a400bbd9 100644
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
import java.lang.invoke.MethodHandle;
import java.util.Iterator;
import java.util.concurrent.Callable;
@@ -39,8 +41,6 @@ import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
/**
* Utilities used by "JSON" object implementation.
*/
@@ -90,7 +90,7 @@ public final class JSONFunctions {
}
final Global global = Context.getGlobal();
- Object unfiltered = convertNode(global, node);
+ final Object unfiltered = convertNode(global, node);
return applyReviver(global, unfiltered, reviver);
}
@@ -122,7 +122,7 @@ public final class JSONFunctions {
if (newElement == ScriptRuntime.UNDEFINED) {
valueObj.delete(key, false);
} else {
- setPropertyValue(valueObj, key, newElement, false);
+ setPropertyValue(valueObj, key, newElement);
}
}
}
@@ -139,8 +139,6 @@ public final class JSONFunctions {
// Converts IR node to runtime value
private static Object convertNode(final Global global, final Node node) {
- assert global instanceof Global;
-
if (node instanceof LiteralNode) {
// check for array literal
if (node.tokenType() == TokenType.ARRAY) {
@@ -181,28 +179,28 @@ public final class JSONFunctions {
final String name = pNode.getKeyName();
final Object value = convertNode(global, valueNode);
- setPropertyValue(object, name, value, false);
+ setPropertyValue(object, name, value);
}
return object;
} else if (node instanceof UnaryNode) {
// UnaryNode used only to represent negative number JSON value
final UnaryNode unaryNode = (UnaryNode)node;
- return -((LiteralNode<?>)unaryNode.rhs()).getNumber();
+ return -((LiteralNode<?>)unaryNode.getExpression()).getNumber();
} else {
return null;
}
}
// add a new property if does not exist already, or else set old property
- private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
+ private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value) {
final int index = ArrayIndex.getArrayIndex(name);
if (ArrayIndex.isValidArrayIndex(index)) {
// array index key
sobj.defineOwnProperty(index, value);
} else if (sobj.getMap().findProperty(name) != null) {
// pre-existing non-inherited property, call set
- sobj.set(name, value, strict);
+ sobj.set(name, value, 0);
} else {
// add new property
sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
diff --git a/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java b/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
index 3c430b29..e1357d6c 100644
--- a/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
@@ -45,12 +45,12 @@ public final class JSObjectListAdapter extends ListAdapter {
}
@Override
- protected Object getAt(int index) {
+ protected Object getAt(final int index) {
return ((JSObject)obj).getSlot(index);
}
@Override
- protected void setAt(int index, Object element) {
+ protected void setAt(final int index, final Object element) {
((JSObject)obj).setSlot(index, element);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/JSType.java b/src/jdk/nashorn/internal/runtime/JSType.java
index 11cecbfe..7e54b1e2 100644
--- a/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/src/jdk/nashorn/internal/runtime/JSType.java
@@ -26,16 +26,20 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Deque;
import java.util.List;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
@@ -72,58 +76,199 @@ public enum JSType {
/** Max value for an uint32 in JavaScript */
public static final long MAX_UINT = 0xFFFF_FFFFL;
- private static final MethodHandles.Lookup myLookup = MethodHandles.lookup();
+ private static final MethodHandles.Lookup JSTYPE_LOOKUP = MethodHandles.lookup();
/** JavaScript compliant conversion function from Object to boolean */
- public static final Call TO_BOOLEAN = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, Object.class);
+ public static final Call TO_BOOLEAN = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, Object.class);
/** JavaScript compliant conversion function from number to boolean */
- public static final Call TO_BOOLEAN_D = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, double.class);
+ public static final Call TO_BOOLEAN_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, double.class);
/** JavaScript compliant conversion function from Object to integer */
- public static final Call TO_INTEGER = staticCall(myLookup, JSType.class, "toInteger", int.class, Object.class);
+ public static final Call TO_INTEGER = staticCall(JSTYPE_LOOKUP, JSType.class, "toInteger", int.class, Object.class);
/** JavaScript compliant conversion function from Object to long */
- public static final Call TO_LONG = staticCall(myLookup, JSType.class, "toLong", long.class, Object.class);
+ public static final Call TO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, Object.class);
+
+ /** JavaScript compliant conversion function from double to long */
+ public static final Call TO_LONG_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, double.class);
/** JavaScript compliant conversion function from Object to number */
- public static final Call TO_NUMBER = staticCall(myLookup, JSType.class, "toNumber", double.class, Object.class);
+ public static final Call TO_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumber", double.class, Object.class);
+
+ /** JavaScript compliant conversion function from Object to number with type check */
+ public static final Call TO_NUMBER_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumberOptimistic", double.class, Object.class, int.class);
/** JavaScript compliant conversion function from Object to String */
- public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class);
+ public static final Call TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, Object.class);
/** JavaScript compliant conversion function from Object to int32 */
- public static final Call TO_INT32 = staticCall(myLookup, JSType.class, "toInt32", int.class, Object.class);
+ public static final Call TO_INT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, Object.class);
+
+ /** JavaScript compliant conversion function from Object to int32 */
+ public static final Call TO_INT32_L = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, long.class);
+
+ /** JavaScript compliant conversion function from Object to int32 with type check */
+ public static final Call TO_INT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32Optimistic", int.class, Object.class, int.class);
/** JavaScript compliant conversion function from double to int32 */
- public static final Call TO_INT32_D = staticCall(myLookup, JSType.class, "toInt32", int.class, double.class);
+ public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class);
- /** JavaScript compliant conversion function from Object to uint32 */
- public static final Call TO_UINT32 = staticCall(myLookup, JSType.class, "toUint32", long.class, Object.class);
+ /** JavaScript compliant conversion function from int to uint32 */
+ public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class);
- /** JavaScript compliant conversion function from number to uint32 */
- public static final Call TO_UINT32_D = staticCall(myLookup, JSType.class, "toUint32", long.class, double.class);
+ /** JavaScript compliant conversion function from Object to uint32 */
+ public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
- /** JavaScript compliant conversion function from Object to int64 */
- public static final Call TO_INT64 = staticCall(myLookup, JSType.class, "toInt64", long.class, Object.class);
+ /** JavaScript compliant conversion function from Object to long with type check */
+ public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class);
- /** JavaScript compliant conversion function from number to int64 */
- public static final Call TO_INT64_D = staticCall(myLookup, JSType.class, "toInt64", long.class, double.class);
+ /** JavaScript compliant conversion function from number to uint32 */
+ public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class);
/** JavaScript compliant conversion function from number to String */
- public static final Call TO_STRING_D = staticCall(myLookup, JSType.class, "toString", String.class, double.class);
+ public static final Call TO_STRING_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, double.class);
/** Combined call to toPrimitive followed by toString. */
- public static final Call TO_PRIMITIVE_TO_STRING = staticCall(myLookup, JSType.class, "toPrimitiveToString", String.class, Object.class);
+ public static final Call TO_PRIMITIVE_TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToString", String.class, Object.class);
+
+ /** Combined call to toPrimitive followed by toCharSequence. */
+ public static final Call TO_PRIMITIVE_TO_CHARSEQUENCE = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToCharSequence", CharSequence.class, Object.class);
+
+ /** Throw an unwarranted optimism exception */
+ public static final Call THROW_UNWARRANTED = staticCall(JSTYPE_LOOKUP, JSType.class, "throwUnwarrantedOptimismException", Object.class, Object.class, int.class);
+
+ /** Add exact wrapper for potentially overflowing integer operations */
+ public static final Call ADD_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", int.class, int.class, int.class, int.class);
+
+ /** Sub exact wrapper for potentially overflowing integer operations */
+ public static final Call SUB_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", int.class, int.class, int.class, int.class);
+
+ /** Multiply exact wrapper for potentially overflowing integer operations */
+ public static final Call MUL_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", int.class, int.class, int.class, int.class);
+
+ /** Div exact wrapper for potentially integer division that turns into float point */
+ public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class);
+
+ /** Div zero wrapper for integer division that handles (0/0)|0 == 0 */
+ public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class);
+
+ /** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */
+ public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class);
+
+ /** Mod exact wrapper for potentially integer remainders that turns into float point */
+ public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class);
+
+ /** Decrement exact wrapper for potentially overflowing integer operations */
+ public static final Call DECREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", int.class, int.class, int.class);
+
+ /** Increment exact wrapper for potentially overflowing integer operations */
+ public static final Call INCREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", int.class, int.class, int.class);
+
+ /** Negate exact exact wrapper for potentially overflowing integer operations */
+ public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class);
+
+ /** Add exact wrapper for potentially overflowing long operations */
+ public static final Call ADD_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class);
+
+ /** Sub exact wrapper for potentially overflowing long operations */
+ public static final Call SUB_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class);
+
+ /** Multiply exact wrapper for potentially overflowing long operations */
+ public static final Call MUL_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class);
+
+ /** Div exact wrapper for potentially integer division that turns into float point */
+ public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class);
+
+ /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */
+ public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class);
+
+ /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */
+ public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class);
+
+ /** Mod exact wrapper for potentially integer remainders that turns into float point */
+ public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class);
+
+ /** Decrement exact wrapper for potentially overflowing long operations */
+ public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", long.class, long.class, int.class);
+
+ /** Increment exact wrapper for potentially overflowing long operations */
+ public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", long.class, long.class, int.class);
+
+ /** Negate exact exact wrapper for potentially overflowing long operations */
+ public static final Call NEGATE_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", long.class, long.class, int.class);
/** Method handle to convert a JS Object to a Java array. */
- public static final Call TO_JAVA_ARRAY = staticCall(myLookup, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
+ public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
/** Method handle to convert a JS Object to a Java List. */
- public static final Call TO_JAVA_LIST = staticCall(myLookup, JSType.class, "toJavaList", List.class, Object.class);
+ public static final Call TO_JAVA_LIST = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaList", List.class, Object.class);
/** Method handle to convert a JS Object to a Java deque. */
- public static final Call TO_JAVA_DEQUE = staticCall(myLookup, JSType.class, "toJavaDeque", Deque.class, Object.class);
+ public static final Call TO_JAVA_DEQUE = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaDeque", Deque.class, Object.class);
+
+ /** Method handle for void returns. */
+ public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class);
+
+
+ /**
+ * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
+ * in the dual--fields world
+ */
+ private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
+ Arrays.asList(
+ Type.INT,
+ Type.LONG,
+ Type.NUMBER,
+ Type.OBJECT));
+
+ /** table index for undefined type - hard coded so it can be used in switches at compile time */
+ public static final int TYPE_UNDEFINED_INDEX = -1;
+ /** table index for integer type - hard coded so it can be used in switches at compile time */
+ public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class);
+ /** table index for long type - hard coded so it can be used in switches at compile time */
+ public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class);
+ /** table index for double type - hard coded so it can be used in switches at compile time */
+ public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class);
+ /** table index for object type - hard coded so it can be used in switches at compile time */
+ public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class);
+
+ /** object conversion quickies with JS semantics - used for return value and parameter filter */
+ public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList(
+ JSType.TO_INT32.methodHandle(),
+ JSType.TO_UINT32.methodHandle(),
+ JSType.TO_NUMBER.methodHandle(),
+ null
+ );
+
+ /**
+ * object conversion quickies with JS semantics - used for return value and parameter filter, optimistic
+ * throws exception upon incompatible type (asking for a narrower one than the storage)
+ */
+ public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList(
+ JSType.TO_INT32_OPTIMISTIC.methodHandle(),
+ JSType.TO_LONG_OPTIMISTIC.methodHandle(),
+ JSType.TO_NUMBER_OPTIMISTIC.methodHandle(),
+ null
+ );
+
+ /** The value of Undefined cast to an int32 */
+ public static final int UNDEFINED_INT = 0;
+ /** The value of Undefined cast to a long */
+ public static final long UNDEFINED_LONG = 0L;
+ /** The value of Undefined cast to a double */
+ public static final double UNDEFINED_DOUBLE = Double.NaN;
+
+ /**
+ * Method handles for getters that return undefined coerced
+ * to the appropriate type
+ */
+ public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList(
+ MH.constant(int.class, UNDEFINED_INT),
+ MH.constant(long.class, UNDEFINED_LONG),
+ MH.constant(double.class, UNDEFINED_DOUBLE),
+ MH.constant(Object.class, Undefined.getUndefined())
+ );
private static final double INT32_LIMIT = 4294967296.0;
@@ -159,7 +304,7 @@ public enum JSType {
}
if (obj instanceof ScriptObject) {
- return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT;
+ return obj instanceof ScriptFunction ? JSType.FUNCTION : JSType.OBJECT;
}
if (obj instanceof Boolean) {
@@ -182,6 +327,52 @@ public enum JSType {
}
/**
+ * Similar to {@link #of(Object)}, but does not distinguish between {@link #FUNCTION} and {@link #OBJECT}, returning
+ * {@link #OBJECT} in both cases. The distinction is costly, and the EQ and STRICT_EQ predicates don't care about it
+ * so we maintain this version for their use.
+ *
+ * @param obj an object
+ *
+ * @return the JSType for the object; returns {@link #OBJECT} instead of {@link #FUNCTION} for functions.
+ */
+ public static JSType ofNoFunction(final Object obj) {
+ // Order of these statements is tuned for performance (see JDK-8024476)
+ if (obj == null) {
+ return JSType.NULL;
+ }
+
+ if (obj instanceof ScriptObject) {
+ return JSType.OBJECT;
+ }
+
+ if (obj instanceof Boolean) {
+ return JSType.BOOLEAN;
+ }
+
+ if (obj instanceof String || obj instanceof ConsString) {
+ return JSType.STRING;
+ }
+
+ if (obj instanceof Number) {
+ return JSType.NUMBER;
+ }
+
+ if (obj == ScriptRuntime.UNDEFINED) {
+ return JSType.UNDEFINED;
+ }
+
+ return JSType.OBJECT;
+ }
+
+ /**
+ * Void return method handle glue
+ */
+ public static void voidReturn() {
+ //empty
+ //TODO: fix up SetMethodCreator better so we don't need this stupid thing
+ }
+
+ /**
* Returns true if double number can be represented as an int
*
* @param number a long to inspect
@@ -193,7 +384,8 @@ public enum JSType {
}
/**
- * Returns true if double number can be represented as an int
+ * Returns true if double number can be represented as an int. Note that it returns true for negative zero. If you
+ * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
*
* @param number a double to inspect
*
@@ -204,7 +396,22 @@ public enum JSType {
}
/**
- * Returns true if double number can be represented as a long
+ * Returns true if Object can be represented as an int
+ *
+ * @param obj an object to inspect
+ *
+ * @return true for int representable objects
+ */
+ public static boolean isRepresentableAsInt(final Object obj) {
+ if (obj instanceof Number) {
+ return isRepresentableAsInt(((Number)obj).doubleValue());
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if double number can be represented as a long. Note that it returns true for negative zero. If you
+ * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
*
* @param number a double to inspect
* @return true for long representable doubles
@@ -214,13 +421,36 @@ public enum JSType {
}
/**
+ * Returns true if Object can be represented as a long
+ *
+ * @param obj an object to inspect
+ *
+ * @return true for long representable objects
+ */
+ public static boolean isRepresentableAsLong(final Object obj) {
+ if (obj instanceof Number) {
+ return isRepresentableAsLong(((Number)obj).doubleValue());
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the number is the negative zero ({@code -0.0d}).
+ * @param number the number to test
+ * @return true if it is the negative zero, false otherwise.
+ */
+ public static boolean isNegativeZero(final double number) {
+ return number == 0.0d && Double.doubleToRawLongBits(number) == 0x8000000000000000L;
+ }
+
+ /**
* Check whether an object is primitive
*
* @param obj an object
*
* @return true if object is primitive (includes null and undefined)
*/
- public static boolean isPrimitive(final Object obj) {
+ public static boolean isPrimitive(final Object obj) {
return obj == null ||
obj == ScriptRuntime.UNDEFINED ||
obj instanceof Boolean ||
@@ -270,11 +500,21 @@ public enum JSType {
*
* @return the string form of the primitive form of the object
*/
- public static String toPrimitiveToString(Object obj) {
+ public static String toPrimitiveToString(final Object obj) {
return toString(toPrimitive(obj));
}
/**
+ * Like {@link #toPrimitiveToString(Object)}, but avoids conversion of ConsString to String.
+ *
+ * @param obj an object
+ * @return the CharSequence form of the primitive form of the object
+ */
+ public static CharSequence toPrimitiveToCharSequence(final Object obj) {
+ return toCharSequence(toPrimitive(obj));
+ }
+
+ /**
* JavaScript compliant conversion of number to boolean
*
* @param num a number
@@ -474,6 +714,9 @@ public enum JSType {
* @return a number
*/
public static double toNumber(final Object obj) {
+ if (obj instanceof Double) {
+ return (Double)obj;
+ }
if (obj instanceof Number) {
return ((Number)obj).doubleValue();
}
@@ -494,6 +737,35 @@ public enum JSType {
}
/**
+ * Optimistic number conversion - throws UnwarrantedOptimismException if Object
+ *
+ * @param obj object to convert
+ * @param programPoint program point
+ * @return double
+ */
+ public static double toNumberOptimistic(final Object obj, final int programPoint) {
+ if (obj != null) {
+ final Class<?> clz = obj.getClass();
+ if (clz == Double.class || clz == Integer.class || clz == Long.class) {
+ return ((Number)obj).doubleValue();
+ }
+ }
+ throw new UnwarrantedOptimismException(obj, programPoint);
+ }
+
+ /**
+ * Object to number conversion that delegates to either {@link #toNumber(Object)} or to
+ * {@link #toNumberOptimistic(Object, int)} depending on whether the program point is valid or not.
+ * @param obj the object to convert
+ * @param programPoint the program point; can be invalid.
+ * @return the value converted to a number
+ * @throws UnwarrantedOptimismException if the value can't be represented as a number and the program point is valid.
+ */
+ public static double toNumberMaybeOptimistic(final Object obj, final int programPoint) {
+ return UnwarrantedOptimismException.isValid(programPoint) ? toNumberOptimistic(obj, programPoint) : toNumber(obj);
+ }
+
+ /**
* Digit representation for a character
*
* @param ch a character
@@ -612,7 +884,7 @@ public enum JSType {
}
/**
- * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger
+ * Converts an Object to long.
*
* <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE}
* for double values that exceed the long range, including positive and negative Infinity. It is the
@@ -622,7 +894,46 @@ public enum JSType {
* @return a long
*/
public static long toLong(final Object obj) {
- return (long)toNumber(obj);
+ return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj));
+ }
+
+ /**
+ * Converts a double to long.
+ *
+ * @param num the double to convert
+ * @return the converted long value
+ */
+ public static long toLong(final double num) {
+ return (long)num;
+ }
+
+ /**
+ * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object
+ *
+ * @param obj object to convert
+ * @param programPoint program point
+ * @return long
+ */
+ public static long toLongOptimistic(final Object obj, final int programPoint) {
+ if (obj != null) {
+ final Class<?> clz = obj.getClass();
+ if (clz == Long.class || clz == Integer.class) {
+ return ((Number)obj).longValue();
+ }
+ }
+ throw new UnwarrantedOptimismException(obj, programPoint);
+ }
+
+ /**
+ * Object to int conversion that delegates to either {@link #toLong(Object)} or to
+ * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not.
+ * @param obj the object to convert
+ * @param programPoint the program point; can be invalid.
+ * @return the value converted to long
+ * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid.
+ */
+ public static long toLongMaybeOptimistic(final Object obj, final int programPoint) {
+ return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj);
}
/**
@@ -637,46 +948,54 @@ public enum JSType {
}
/**
- * JavaScript compliant long to int32 conversion
+ * Optimistic int conversion - throws UnwarrantedOptimismException if double, long or Object
*
- * @param num a long
- * @return an int32
+ * @param obj object to convert
+ * @param programPoint program point
+ * @return double
*/
- public static int toInt32(final long num) {
- return (int)num;
+ public static int toInt32Optimistic(final Object obj, final int programPoint) {
+ if (obj != null && obj.getClass() == Integer.class) {
+ return ((Integer)obj).intValue();
+ }
+ throw new UnwarrantedOptimismException(obj, programPoint);
}
/**
- * JavaScript compliant number to int32 conversion
- *
- * @param num a number
- * @return an int32
+ * Object to int conversion that delegates to either {@link #toInt32(Object)} or to
+ * {@link #toInt32Optimistic(Object, int)} depending on whether the program point is valid or not.
+ * @param obj the object to convert
+ * @param programPoint the program point; can be invalid.
+ * @return the value converted to int
+ * @throws UnwarrantedOptimismException if the value can't be represented as int and the program point is valid.
*/
- public static int toInt32(final double num) {
- return (int)doubleToInt32(num);
+ public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) {
+ return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj);
}
+ // Minimum and maximum range between which every long value can be precisely represented as a double.
+ private static final long MAX_PRECISE_DOUBLE = 1L << 53;
+ private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE;
+
/**
- * JavaScript compliant Object to int64 conversion
+ * JavaScript compliant long to int32 conversion
*
- * @param obj an object
- * @return an int64
+ * @param num a long
+ * @return an int32
*/
- public static long toInt64(final Object obj) {
- return toInt64(toNumber(obj));
+ public static int toInt32(final long num) {
+ return (int)(num >= MIN_PRECISE_DOUBLE && num <= MAX_PRECISE_DOUBLE ? num : (long)(num % INT32_LIMIT));
}
+
/**
- * JavaScript compliant number to int64 conversion
+ * JavaScript compliant number to int32 conversion
*
* @param num a number
- * @return an int64
+ * @return an int32
*/
- public static long toInt64(final double num) {
- if (Double.isInfinite(num)) {
- return 0L;
- }
- return (long)num;
+ public static int toInt32(final double num) {
+ return (int)doubleToInt32(num);
}
/**
@@ -700,6 +1019,16 @@ public enum JSType {
}
/**
+ * JavaScript compliant int to uint32 conversion
+ *
+ * @param num an int
+ * @return a uint32
+ */
+ public static long toUint32(final int num) {
+ return num & MAX_UINT;
+ }
+
+ /**
* JavaScript compliant Object to uint16 conversion
* ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
*
@@ -727,7 +1056,7 @@ public enum JSType {
* @return a uint16
*/
public static int toUint16(final long num) {
- return ((int)num) & 0xffff;
+ return (int)num & 0xffff;
}
/**
@@ -737,7 +1066,7 @@ public enum JSType {
* @return a uint16
*/
public static int toUint16(final double num) {
- return ((int)doubleToInt32(num)) & 0xffff;
+ return (int)doubleToInt32(num) & 0xffff;
}
private static long doubleToInt32(final double num) {
@@ -751,7 +1080,7 @@ public enum JSType {
return 0;
}
// This is rather slow and could probably be sped up using bit-fiddling.
- final double d = (num >= 0) ? Math.floor(num) : Math.ceil(num);
+ final double d = num >= 0 ? Math.floor(num) : Math.ceil(num);
return (long)(d % INT32_LIMIT);
}
@@ -1014,6 +1343,448 @@ public enum JSType {
return str.substring(start);
}
+ /**
+ * Throw an unwarranted optimism exception for a program point
+ * @param value real return value
+ * @param programPoint program point
+ * @return
+ */
+ @SuppressWarnings("unused")
+ private static Object throwUnwarrantedOptimismException(final Object value, final int programPoint) {
+ throw new UnwarrantedOptimismException(value, programPoint);
+ }
+
+ /**
+ * Wrapper for addExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.addExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((long)x + (long)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for addExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.addExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((double)x + (double)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for subExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.subtractExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((long)x - (long)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for subExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.subtractExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((double)x - (double)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for mulExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.multiplyExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((long)x * (long)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for mulExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.multiplyExact(x, y);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((double)x * (double)y, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as
+ * int.
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if the result of the division can't be represented as int.
+ */
+ public static int divExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+ final int res;
+ try {
+ res = x / y;
+ } catch (final ArithmeticException e) {
+ assert y == 0; // Only div by zero anticipated
+ throw new UnwarrantedOptimismException(x > 0 ? Double.POSITIVE_INFINITY : x < 0 ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint);
+ }
+ final int rem = x % y;
+ if (rem == 0) {
+ return res;
+ }
+ // go directly to double here, as anything with non zero remainder is a floating point number in JavaScript
+ throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
+ }
+
+ /**
+ * Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to
+ * {@code (x / y)|0} JavaScript expression (division of two ints coerced to int).
+ * @param x the dividend
+ * @param y the divisor
+ * @return the result
+ */
+ public static int divZero(final int x, final int y) {
+ return y == 0 ? 0 : x / y;
+ }
+
+ /**
+ * Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to
+ * {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int).
+ * @param x the dividend
+ * @param y the divisor
+ * @return the remainder
+ */
+ public static int remZero(final int x, final int y) {
+ return y == 0 ? 0 : x % y;
+ }
+
+ /**
+ * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if the modulo can't be represented as int.
+ */
+ public static int remExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return x % y;
+ } catch (final ArithmeticException e) {
+ assert y == 0; // Only mod by zero anticipated
+ throw new UnwarrantedOptimismException(Double.NaN, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as
+ * long.
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if the result of the division can't be represented as long.
+ */
+ public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+ final long res;
+ try {
+ res = x / y;
+ } catch (final ArithmeticException e) {
+ assert y == 0L; // Only div by zero anticipated
+ throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint);
+ }
+ final long rem = x % y;
+ if (rem == 0L) {
+ return res;
+ }
+ throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
+ }
+
+ /**
+ * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs
+ * is coerced to long.
+ * @param x the dividend
+ * @param y the divisor
+ * @return the result
+ */
+ public static long divZero(final long x, final long y) {
+ return y == 0L ? 0L : x / y;
+ }
+
+ /**
+ * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs
+ * is coerced to long.
+ * @param x the dividend
+ * @param y the divisor
+ * @return the remainder
+ */
+ public static long remZero(final long x, final long y) {
+ return y == 0L ? 0L : x % y;
+ }
+
+ /**
+ * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
+ *
+ * @param x first term
+ * @param y second term
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if the modulo can't be represented as int.
+ */
+ public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return x % y;
+ } catch (final ArithmeticException e) {
+ assert y == 0L; // Only mod by zero anticipated
+ throw new UnwarrantedOptimismException(Double.NaN, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for decrementExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x number to negate
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.decrementExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((long)x - 1, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for decrementExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x number to negate
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.decrementExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((double)x - 1L, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for incrementExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x the number to increment
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.incrementExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((long)x + 1, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for incrementExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x the number to increment
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ return Math.incrementExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException((double)x + 1L, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for negateExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x the number to negate
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static int negateExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ if (x == 0) {
+ throw new UnwarrantedOptimismException(-0.0, programPoint);
+ }
+ return Math.negateExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException(-(long)x, programPoint);
+ }
+ }
+
+ /**
+ * Wrapper for negateExact
+ *
+ * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+ * containing the result and the program point of the failure
+ *
+ * @param x the number to negate
+ * @param programPoint program point id
+ * @return the result
+ * @throws UnwarrantedOptimismException if overflow occurs
+ */
+ public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+ try {
+ if (x == 0L) {
+ throw new UnwarrantedOptimismException(-0.0, programPoint);
+ }
+ return Math.negateExact(x);
+ } catch (final ArithmeticException e) {
+ throw new UnwarrantedOptimismException(-(double)x, programPoint);
+ }
+ }
+
+ /**
+ * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes())
+ *
+ * @param type the type
+ *
+ * @return the accessor index, or -1 if no accessor of this type exists
+ */
+ public static int getAccessorTypeIndex(final Type type) {
+ return getAccessorTypeIndex(type.getTypeClass());
+ }
+
+ /**
+ * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes())
+ *
+ * Note that this is hardcoded with respect to the dynamic contents of the accessor
+ * types array for speed. Hotspot got stuck with this as 5% of the runtime in
+ * a benchmark when it looped over values and increased an index counter. :-(
+ *
+ * @param type the type
+ *
+ * @return the accessor index, or -1 if no accessor of this type exists
+ */
+ public static int getAccessorTypeIndex(final Class<?> type) {
+ if (type == null) {
+ return TYPE_UNDEFINED_INDEX;
+ } else if (type == int.class) {
+ return TYPE_INT_INDEX;
+ } else if (type == long.class) {
+ return TYPE_LONG_INDEX;
+ } else if (type == double.class) {
+ return TYPE_DOUBLE_INDEX;
+ } else if (!type.isPrimitive()) {
+ return TYPE_OBJECT_INDEX;
+ }
+ return -1;
+ }
+
+ /**
+ * Return the accessor type based on its index in [0..getNumberOfAccessorTypes())
+ * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always
+ * go to a type of higher index
+ *
+ * @param index accessor type index
+ *
+ * @return a type corresponding to the index.
+ */
+
+ public static Type getAccessorType(final int index) {
+ return ACCESSOR_TYPES.get(index);
+ }
+
+ /**
+ * Return the number of accessor types available.
+ *
+ * @return number of accessor types in system
+ */
+ public static int getNumberOfAccessorTypes() {
+ return ACCESSOR_TYPES.size();
+ }
+
private static double parseRadix(final char chars[], final int start, final int length, final int radix) {
int pos = 0;
@@ -1074,4 +1845,67 @@ public enum JSType {
throw new RuntimeException(t);
}
}
+
+ /**
+ * Returns the boxed version of a primitive class
+ * @param clazz the class
+ * @return the boxed type of clazz, or unchanged if not primitive
+ */
+ public static Class<?> getBoxedClass(final Class<?> clazz) {
+ if (clazz == int.class) {
+ return Integer.class;
+ } else if (clazz == long.class) {
+ return Long.class;
+ } else if (clazz == double.class) {
+ return Double.class;
+ }
+ assert !clazz.isPrimitive();
+ return clazz;
+ }
+
+ /**
+ * Create a method handle constant of the correct primitive type
+ * for a constant object
+ * @param o object
+ * @return constant function that returns object
+ */
+ public static MethodHandle unboxConstant(final Object o) {
+ if (o != null) {
+ if (o.getClass() == Integer.class) {
+ return MH.constant(int.class, ((Integer)o).intValue());
+ } else if (o.getClass() == Long.class) {
+ return MH.constant(long.class, ((Long)o).longValue());
+ } else if (o.getClass() == Double.class) {
+ return MH.constant(double.class, ((Double)o).doubleValue());
+ }
+ }
+ return MH.constant(Object.class, o);
+ }
+
+ /**
+ * Get the unboxed (primitive) type for an object
+ * @param o object
+ * @return primive type or Object.class if not primitive
+ */
+ public static Class<?> unboxedFieldType(final Object o) {
+ if (OBJECT_FIELDS_ONLY) {
+ return Object.class;
+ }
+
+ if (o == null) {
+ return Object.class;
+ } else if (o.getClass() == Integer.class) {
+ return int.class;
+ } else if (o.getClass() == Long.class) {
+ return long.class;
+ } else if (o.getClass() == Double.class) {
+ return double.class;
+ } else {
+ return Object.class;
+ }
+ }
+
+ private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) {
+ return Collections.unmodifiableList(Arrays.asList(methodHandles));
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/ListAdapter.java b/src/jdk/nashorn/internal/runtime/ListAdapter.java
index 9a3408fb..25179a59 100644
--- a/src/jdk/nashorn/internal/runtime/ListAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -34,7 +34,6 @@ import java.util.RandomAccess;
import java.util.concurrent.Callable;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
-import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -174,7 +173,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
*/
protected abstract void setAt(final int index, final Object element);
- private void checkRange(int index) {
+ private void checkRange(final int index) {
if(index < 0 || index >= size()) {
throw invalidIndex(index);
}
@@ -200,7 +199,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
unshiftInvoker.getInvoker().invokeExact(fn, obj, e);
} catch(RuntimeException | Error ex) {
throw ex;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
@@ -214,7 +213,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
pushInvoker.getInvoker().invokeExact(fn, obj, e);
} catch(RuntimeException | Error ex) {
throw ex;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
@@ -328,7 +327,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
return shiftInvoker.getInvoker().invokeExact(fn, obj);
} catch(RuntimeException | Error ex) {
throw ex;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
@@ -341,7 +340,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
return popInvoker.getInvoker().invokeExact(fn, obj);
} catch(RuntimeException | Error ex) {
throw ex;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
@@ -359,7 +358,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
spliceRemoveInvoker.getInvoker().invokeExact(fn, obj, fromIndex, count);
} catch(RuntimeException | Error ex) {
throw ex;
- } catch(Throwable t) {
+ } catch(final Throwable t) {
throw new RuntimeException(t);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/Logging.java b/src/jdk/nashorn/internal/runtime/Logging.java
deleted file mode 100644
index 54d83b79..00000000
--- a/src/jdk/nashorn/internal/runtime/Logging.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-import java.util.logging.LoggingPermission;
-
-/**
- * Logging system for getting loggers for arbitrary subsystems as
- * specified on the command line. Supports all standard log levels
- *
- */
-public final class Logging {
-
- private Logging() {
- }
-
- /** Loggers */
-
- private static final Logger disabledLogger = Logger.getLogger("disabled");
-
- private static AccessControlContext createLoggerControlAccCtxt() {
- final Permissions perms = new Permissions();
- perms.add(new LoggingPermission("control", null));
- return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
- }
-
- static {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- Logging.disabledLogger.setLevel(Level.OFF);
- return null;
- }
- }, createLoggerControlAccCtxt());
- }
-
- /** Maps logger name to loggers. Names are typically per package */
- private static final Map<String, Logger> loggers = new HashMap<>();
-
- private static String lastPart(final String packageName) {
- final String[] parts = packageName.split("\\.");
- if (parts.length == 0) {
- return packageName;
- }
- return parts[parts.length - 1];
- }
-
- /**
- * Get a logger for a given class, generating a logger name based on the
- * class name
- *
- * @param name the name to use as key for the logger
- * @return the logger
- */
- public static Logger getLogger(final String name) {
- final Logger logger = Logging.loggers.get(name);
- if (logger != null) {
- return logger;
- }
- return Logging.disabledLogger;
- }
-
- /**
- * Get a logger for a given name or create it if not already there, typically
- * used for mapping system properties to loggers
- *
- * @param name the name to use as key
- * @param level log lever to reset existing logger with, or create new logger with
- * @return the logger
- */
- public static Logger getOrCreateLogger(final String name, final Level level) {
- final Logger logger = Logging.loggers.get(name);
- if (logger == null) {
- return instantiateLogger(name, level);
- }
- logger.setLevel(level);
- return logger;
- }
-
- /**
- * Initialization function that is called to instantiate the logging system. It takes
- * logger names (keys) and logging labels respectively
- *
- * @param map a map where the key is a logger name and the value a logging level
- * @throws IllegalArgumentException if level or names cannot be parsed
- */
- public static void initialize(final Map<String, String> map) throws IllegalArgumentException {
- try {
- for (final Entry<String, String> entry : map.entrySet()) {
- Level level;
-
- final String key = entry.getKey();
- final String value = entry.getValue();
- if ("".equals(value)) {
- level = Level.INFO;
- } else {
- level = Level.parse(value.toUpperCase(Locale.ENGLISH));
- }
-
- final String name = Logging.lastPart(key);
- final Logger logger = instantiateLogger(name, level);
-
- Logging.loggers.put(name, logger);
- }
- } catch (final IllegalArgumentException | SecurityException e) {
- throw e;
- }
- }
-
- private static Logger instantiateLogger(final String name, final Level level) {
- final Logger logger = java.util.logging.Logger.getLogger(name);
- for (final Handler h : logger.getHandlers()) {
- logger.removeHandler(h);
- }
-
- logger.setLevel(level);
- logger.setUseParentHandlers(false);
- final Handler c = new ConsoleHandler();
-
- c.setFormatter(new Formatter() {
- @Override
- public String format(final LogRecord record) {
- final StringBuilder sb = new StringBuilder();
-
- sb.append('[')
- .append(record.getLoggerName())
- .append("] ")
- .append(record.getMessage())
- .append('\n');
-
- return sb.toString();
- }
- });
- logger.addHandler(c);
- c.setLevel(level);
-
- return logger;
- }
-
-}
diff --git a/src/jdk/nashorn/internal/runtime/NashornLoader.java b/src/jdk/nashorn/internal/runtime/NashornLoader.java
index e7837013..423b87db 100644
--- a/src/jdk/nashorn/internal/runtime/NashornLoader.java
+++ b/src/jdk/nashorn/internal/runtime/NashornLoader.java
@@ -92,7 +92,7 @@ abstract class NashornLoader extends SecureClassLoader {
}
@Override
- protected PermissionCollection getPermissions(CodeSource codesource) {
+ protected PermissionCollection getPermissions(final CodeSource codesource) {
final Permissions permCollection = new Permissions();
for (final Permission perm : SCRIPT_PERMISSIONS) {
permCollection.add(perm);
diff --git a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index fbca1c34..2d110e08 100644
--- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -25,10 +25,14 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -135,12 +139,12 @@ public final class NativeJavaPackage extends ScriptObject {
}
@Override
- protected GuardedInvocation findNewMethod(CallSiteDescriptor desc) {
+ protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return createClassNotFoundInvocation(desc);
}
@Override
- protected GuardedInvocation findCallMethod(CallSiteDescriptor desc, LinkRequest request) {
+ protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return createClassNotFoundInvocation(desc);
}
@@ -202,8 +206,12 @@ public final class NativeJavaPackage extends ScriptObject {
}
@Override
- protected Object invokeNoSuchProperty(final String name) {
- return createProperty(name);
+ protected Object invokeNoSuchProperty(final String key, final int programPoint) {
+ final Object retval = createProperty(key);
+ if (isValid(programPoint)) {
+ throw new UnwarrantedOptimismException(retval, programPoint);
+ }
+ return retval;
}
@Override
@@ -226,6 +234,35 @@ public final class NativeJavaPackage extends ScriptObject {
//ignored
}
+ // Check for explicit constructor signature use
+ // Example: new (java.awt["Color(int, int,int)"])(2, 3, 4);
+ final int openBrace = propertyName.indexOf('(');
+ final int closeBrace = propertyName.lastIndexOf(')');
+ if (openBrace != -1 || closeBrace != -1) {
+ final int lastChar = propertyName.length() - 1;
+ if (openBrace == -1 || closeBrace != lastChar) {
+ throw typeError("improper.constructor.signature", propertyName);
+ }
+
+ // get the class name and try to load it
+ final String className = name + "." + propertyName.substring(0, openBrace);
+ try {
+ javaClass = context.findClass(className);
+ } catch (final NoClassDefFoundError | ClassNotFoundException e) {
+ throw typeError(e, "no.such.java.class", className);
+ }
+
+ // try to find a matching constructor
+ final Object constructor = BeansLinker.getConstructorMethod(
+ javaClass, propertyName.substring(openBrace + 1, lastChar));
+ if (constructor != null) {
+ set(propertyName, constructor, 0);
+ return constructor;
+ }
+ // we didn't find a matching constructor!
+ throw typeError("no.such.java.constructor", propertyName);
+ }
+
final Object propertyValue;
if (javaClass == null) {
propertyValue = new NativeJavaPackage(fullName, getProto());
@@ -233,7 +270,7 @@ public final class NativeJavaPackage extends ScriptObject {
propertyValue = StaticClass.forClass(javaClass);
}
- set(propertyName, propertyValue, false);
+ set(propertyName, propertyValue, 0);
return propertyValue;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java b/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java
new file mode 100644
index 00000000..6829ddeb
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
+
+/**
+ * This is an interface for classes that need custom linkage logic. This means Native objects
+ * that contain optimistic native methods, that need special/extra rules for linking, guards and
+ * SwitchPointing, known and internal to the Native object for its linkage
+ */
+public interface OptimisticBuiltins {
+
+ /**
+ * Return an instance of the linking logic we need for a particular LinkLogic
+ * subclass, gotten from the compile time annotation of a specialized builtin method
+ * No assumptions can be made about the lifetime of the instance. The receiver may
+ * keep it as a perpetual final instance field or create new linking logic depending
+ * on its current state for each call, depending on if the global state has changed
+ * or other factors
+ *
+ * @param clazz linking logic class
+ * @return linking logic instance for this class
+ */
+ public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz);
+
+ /**
+ * Does this link logic vary depending on which instance we are working with.
+ * Then we have to sort out certain primitives, as they are created as new
+ * objects in the wrapFilter by JavaScript semantics. An example of instance only
+ * assumptions are switchPoints per instance, as in NativeArray. NativeString is
+ * fine, as it's only static.
+ *
+ * TODO: finer granularity on this, on the function level so certain functions
+ * are forbidden only. Currently we don't have enough specialization to bump into this
+ *
+ * @return true if there are per instance assumptions for the optimism
+ */
+ public boolean hasPerInstanceAssumptions();
+
+}
diff --git a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
new file mode 100644
index 00000000..e93fe602
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.support.TypeUtilities;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+
+/**
+ * Optimistic return value filters
+ */
+public final class OptimisticReturnFilters {
+ private static final MethodHandle[] ENSURE_INT;
+ private static final MethodHandle[] ENSURE_LONG;
+ private static final MethodHandle[] ENSURE_NUMBER;
+
+ private static final int BOOLEAN_TYPE_INDEX;
+ private static final int CHAR_TYPE_INDEX;
+ private static final int FLOAT_TYPE_INDEX;
+ private static final int VOID_TYPE_INDEX;
+
+ static {
+ final MethodHandle INT_DOUBLE = findOwnMH("ensureInt", int.class, double.class, int.class);
+ ENSURE_INT = new MethodHandle[] {
+ null,
+ findOwnMH("ensureInt", int.class, long.class, int.class),
+ INT_DOUBLE,
+ findOwnMH("ensureInt", int.class, Object.class, int.class),
+ findOwnMH("ensureInt", int.class, int.class),
+ findOwnMH("ensureInt", int.class, boolean.class, int.class),
+ findOwnMH("ensureInt", int.class, char.class, int.class),
+ INT_DOUBLE.asType(INT_DOUBLE.type().changeParameterType(0, float.class)),
+ };
+
+ VOID_TYPE_INDEX = ENSURE_INT.length - 4;
+ BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 3;
+ CHAR_TYPE_INDEX = ENSURE_INT.length - 2;
+ FLOAT_TYPE_INDEX = ENSURE_INT.length - 1;
+
+ final MethodHandle LONG_DOUBLE = findOwnMH("ensureLong", long.class, double.class, int.class);
+ ENSURE_LONG = new MethodHandle[] {
+ null,
+ null,
+ LONG_DOUBLE,
+ findOwnMH("ensureLong", long.class, Object.class, int.class),
+ ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(long.class)),
+ ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(long.class)),
+ ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(long.class)),
+ LONG_DOUBLE.asType(LONG_DOUBLE.type().changeParameterType(0, float.class)),
+ };
+
+ ENSURE_NUMBER = new MethodHandle[] {
+ null,
+ null,
+ null,
+ findOwnMH("ensureNumber", double.class, Object.class, int.class),
+ ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(double.class)),
+ ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(double.class)),
+ ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(double.class)),
+ null
+ };
+ }
+
+ /**
+ * Given a method handle and an expected return type, perform return value filtering
+ * according to the optimistic type coercion rules
+ * @param mh method handle
+ * @param expectedReturnType expected return type
+ * @param programPoint program point
+ * @return filtered method
+ */
+ public static MethodHandle filterOptimisticReturnValue(final MethodHandle mh, final Class<?> expectedReturnType, final int programPoint) {
+ if(!isValid(programPoint)) {
+ return mh;
+ }
+
+ final MethodType type = mh.type();
+ final Class<?> actualReturnType = type.returnType();
+ if(TypeUtilities.isConvertibleWithoutLoss(actualReturnType, expectedReturnType)) {
+ return mh;
+ }
+
+ final MethodHandle guard = getOptimisticTypeGuard(expectedReturnType, actualReturnType);
+ return guard == null ? mh : MH.filterReturnValue(mh, MH.insertArguments(guard, guard.type().parameterCount() - 1, programPoint));
+ }
+
+ /**
+ * Given a guarded invocation and a callsite descriptor, perform return value filtering
+ * according to the optimistic type coercion rules, using the return value from the descriptor
+ * @param inv the invocation
+ * @param desc the descriptor
+ * @return filtered invocation
+ */
+ public static GuardedInvocation filterOptimisticReturnValue(final GuardedInvocation inv, final CallSiteDescriptor desc) {
+ if(!NashornCallSiteDescriptor.isOptimistic(desc)) {
+ return inv;
+ }
+ return inv.replaceMethods(filterOptimisticReturnValue(inv.getInvocation(), desc.getMethodType().returnType(),
+ NashornCallSiteDescriptor.getProgramPoint(desc)), inv.getGuard());
+ }
+
+ private static MethodHandle getOptimisticTypeGuard(final Class<?> actual, final Class<?> provable) {
+ final MethodHandle guard;
+ final int provableTypeIndex = getProvableTypeIndex(provable);
+ if (actual == int.class) {
+ guard = ENSURE_INT[provableTypeIndex];
+ } else if (actual == long.class) {
+ guard = ENSURE_LONG[provableTypeIndex];
+ } else if (actual == double.class) {
+ guard = ENSURE_NUMBER[provableTypeIndex];
+ } else {
+ guard = null;
+ assert !actual.isPrimitive() : actual + ", " + provable;
+ }
+ if(guard != null && !(provable.isPrimitive())) {
+ // Make sure filtering a MethodHandle(...)String works with a filter MethodHandle(Object, int)... Note that
+ // if the return type of the method is incompatible with Number, then the guard will always throw an
+ // UnwarrantedOperationException when invoked, but we must link it anyway as we need the guarded function to
+ // successfully execute and return the non-convertible return value that it'll put into the thrown
+ // UnwarrantedOptimismException.
+ return guard.asType(guard.type().changeParameterType(0, provable));
+ }
+ return guard;
+ }
+
+ private static int getProvableTypeIndex(final Class<?> provable) {
+ final int accTypeIndex = getAccessorTypeIndex(provable);
+ if(accTypeIndex != -1) {
+ return accTypeIndex;
+ } else if(provable == boolean.class) {
+ return BOOLEAN_TYPE_INDEX;
+ } else if(provable == void.class) {
+ return VOID_TYPE_INDEX;
+ } else if(provable == byte.class || provable == short.class) {
+ return 0; // never needs a guard, as it's assignable to int
+ } else if(provable == char.class) {
+ return CHAR_TYPE_INDEX;
+ } else if(provable == float.class) {
+ return FLOAT_TYPE_INDEX;
+ }
+ throw new AssertionError(provable.getName());
+ }
+
+ //maps staticallyProvableCallSiteType to actualCallSiteType, throws exception if impossible
+ @SuppressWarnings("unused")
+ private static int ensureInt(final long arg, final int programPoint) {
+ if (JSType.isRepresentableAsInt(arg)) {
+ return (int)arg;
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ @SuppressWarnings("unused")
+ private static int ensureInt(final double arg, final int programPoint) {
+ if (JSType.isRepresentableAsInt(arg) && !JSType.isNegativeZero(arg)) {
+ return (int)arg;
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ /**
+ * Returns the argument value as an int. If the argument is not a wrapper for a primitive numeric type
+ * with a value that can be exactly represented as an int, throw an {@link UnwarrantedOptimismException}.
+ * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_INT}.
+ * @param arg the original argument.
+ * @param programPoint the program point used in the exception
+ * @return the value of the argument as an int.
+ * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with
+ * a value that can be exactly represented as an int.
+ */
+ public static int ensureInt(final Object arg, final int programPoint) {
+ // NOTE: this doesn't delegate to ensureInt(double, int) as in that case if arg were a Long, it would throw a
+ // (potentially imprecise) Double in the UnwarrantedOptimismException. This way, it will put the correct valued
+ // Long into the exception.
+ if (isPrimitiveNumberWrapper(arg)) {
+ final double d = ((Number)arg).doubleValue();
+ if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) {
+ return (int)d;
+ }
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ private static boolean isPrimitiveNumberWrapper(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ final Class<?> c = obj.getClass();
+ return c == Integer.class || c == Double.class || c == Long.class ||
+ c == Float.class || c == Short.class || c == Byte.class;
+ }
+
+ @SuppressWarnings("unused")
+ private static int ensureInt(final boolean arg, final int programPoint) {
+ throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
+ }
+
+ @SuppressWarnings("unused")
+ private static int ensureInt(final char arg, final int programPoint) {
+ throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
+ }
+
+ @SuppressWarnings("unused")
+ private static int ensureInt(final int programPoint) {
+ // Turns a void into UNDEFINED
+ throw new UnwarrantedOptimismException(ScriptRuntime.UNDEFINED, programPoint, Type.OBJECT);
+ }
+
+ private static long ensureLong(final double arg, final int programPoint) {
+ if (JSType.isRepresentableAsLong(arg) && !JSType.isNegativeZero(arg)) {
+ return (long)arg;
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ /**
+ * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type
+ * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}.
+ * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}.
+ * @param arg the original argument.
+ * @param programPoint the program point used in the exception
+ * @return the value of the argument as a long.
+ * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with
+ * a value that can be exactly represented as a long
+ */
+ public static long ensureLong(final Object arg, final int programPoint) {
+ if (arg != null) {
+ final Class<?> c = arg.getClass();
+ if (c == Long.class) {
+ // Must check for Long separately, as Long.doubleValue() isn't precise.
+ return ((Long)arg).longValue();
+ } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class ||
+ c == Byte.class) {
+ return ensureLong(((Number)arg).doubleValue(), programPoint);
+ }
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ /**
+ * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type
+ * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
+ * can use it. See {code CodeGenerator.ENSURE_NUMBER}.
+ * @param arg the original argument.
+ * @param programPoint the program point used in the exception
+ * @return the value of the argument as a double.
+ * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type.
+ */
+ public static double ensureNumber(final Object arg, final int programPoint) {
+ if (isPrimitiveNumberWrapper(arg)) {
+ return ((Number)arg).doubleValue();
+ }
+ throw new UnwarrantedOptimismException(arg, programPoint);
+ }
+
+ private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), OptimisticReturnFilters.class, name, MH.type(rtype, types));
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/Property.java b/src/jdk/nashorn/internal/runtime/Property.java
index b3f1e0af..4225c251 100644
--- a/src/jdk/nashorn/internal/runtime/Property.java
+++ b/src/jdk/nashorn/internal/runtime/Property.java
@@ -28,12 +28,11 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
-
import java.io.Serializable;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.SwitchPoint;
import java.util.Objects;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.codegen.types.Type;
/**
* This is the abstract superclass representing a JavaScript Property.
@@ -65,42 +64,57 @@ public abstract class Property implements Serializable {
/** ECMA 8.6.1 - Is this property not configurable? */
public static final int NOT_CONFIGURABLE = 1 << 2;
- private static final int MODIFY_MASK = (NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE);
-
- /** Is this a spill property? See {@link AccessorProperty} */
- public static final int IS_SPILL = 1 << 3;
+ private static final int MODIFY_MASK = NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE;
/** Is this a function parameter? */
- public static final int IS_PARAMETER = 1 << 4;
+ public static final int IS_PARAMETER = 1 << 3;
/** Is parameter accessed thru arguments? */
- public static final int HAS_ARGUMENTS = 1 << 5;
+ public static final int HAS_ARGUMENTS = 1 << 4;
- /** Is this property always represented as an Object? See {@link ObjectClassGenerator} and dual fields flag. */
- public static final int IS_ALWAYS_OBJECT = 1 << 6;
-
- /** Can this property be primitive? */
- public static final int CAN_BE_PRIMITIVE = 1 << 7;
+ /** Is this a function declaration property ? */
+ public static final int IS_FUNCTION_DECLARATION = 1 << 5;
- /** Can this property be undefined? */
- public static final int CAN_BE_UNDEFINED = 1 << 8;
+ /**
+ * Is this is a primitive field given to us by Nasgen, i.e.
+ * something we can be sure remains a constant whose type
+ * is narrower than object, e.g. Math.PI which is declared
+ * as a double
+ */
+ public static final int IS_NASGEN_PRIMITIVE = 1 << 6;
- /** Is this a function declaration property ? */
- public static final int IS_FUNCTION_DECLARATION = 1 << 9;
+ /** Is this a builtin property, e.g. Function.prototype.apply */
+ public static final int IS_BUILTIN = 1 << 7;
/** Is this property bound to a receiver? This means get/set operations will be delegated to
* a statically defined object instead of the object passed as callsite parameter. */
- public static final int IS_BOUND = 1 << 10;
+ public static final int IS_BOUND = 1 << 8;
+
+ /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */
+ public static final int NEEDS_DECLARATION = 1 << 9;
+
+ /** Is this property an ES6 lexical binding? */
+ public static final int IS_LEXICAL_BINDING = 1 << 10;
/** Property key. */
private final String key;
/** Property flags. */
- protected int flags;
+ private int flags;
/** Property field number or spill slot. */
private final int slot;
+ /**
+ * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
+ * null means undefined, and primitive types are allowed. The reason a special type is used for
+ * undefined, is that are no bits left to represent it in primitive types
+ */
+ private Class<?> type;
+
+ /** SwitchPoint that is invalidated when property is changed, optional */
+ protected transient SwitchPoint builtinSwitchPoint;
+
private static final long serialVersionUID = 2099814273074501176L;
/**
@@ -122,10 +136,11 @@ public abstract class Property implements Serializable {
*
* @param property source property
*/
- Property(final Property property) {
- this.key = property.key;
- this.flags = property.flags;
- this.slot = property.slot;
+ Property(final Property property, final int flags) {
+ this.key = property.key;
+ this.slot = property.slot;
+ this.builtinSwitchPoint = property.builtinSwitchPoint;
+ this.flags = flags;
}
/**
@@ -133,7 +148,15 @@ public abstract class Property implements Serializable {
*
* @return cloned property
*/
- abstract Property copy();
+ public abstract Property copy();
+
+ /**
+ * Copy function
+ *
+ * @param newType new type
+ * @return cloned property with new type
+ */
+ public abstract Property copy(final Class<?> newType);
/**
* Property flag utility method for {@link PropertyDescriptor}s. Given two property descriptors,
@@ -166,6 +189,34 @@ public abstract class Property implements Serializable {
}
/**
+ * Set the change callback for this property, i.e. a SwitchPoint
+ * that will be invalidated when the value of the property is
+ * changed
+ * @param sp SwitchPoint to use for change callback
+ */
+ public final void setBuiltinSwitchPoint(final SwitchPoint sp) {
+ this.builtinSwitchPoint = sp;
+ }
+
+ /**
+ * Builtin properties have an invalidation switchpoint that is
+ * invalidated when they are set, this is a getter for it
+ * @return builtin switchpoint, or null if none
+ */
+ public final SwitchPoint getBuiltinSwitchPoint() {
+ return builtinSwitchPoint;
+ }
+
+ /**
+ * Checks if this is a builtin property, this means that it has
+ * a builtin switchpoint that hasn't been invalidated by a setter
+ * @return true if builtin, untouched (unset) property
+ */
+ public boolean isBuiltin() {
+ return builtinSwitchPoint != null && !builtinSwitchPoint.hasBeenInvalidated();
+ }
+
+ /**
* Property flag utility method for {@link PropertyDescriptor}. Get the property flags
* conforming to any Property using this PropertyDescriptor
*
@@ -255,7 +306,7 @@ public abstract class Property implements Serializable {
* @return true if spill property
*/
public boolean isSpill() {
- return (flags & IS_SPILL) == IS_SPILL;
+ return false;
}
/**
@@ -269,15 +320,12 @@ public abstract class Property implements Serializable {
}
/**
- * Does this property use any slots in the spill array described in
- * {@link Property#isSpill}? In that case how many. Currently a property
- * only uses max one spill slot, but this may change in future representations
- * Only {@link AccessorProperty} instances use spill slots
+ * Is this a LET or CONST property that needs to see its declaration before being usable?
*
- * @return number of spill slots a property is using
+ * @return true if this is a block-scoped variable
*/
- public int getSpillCount() {
- return isSpill() ? 1 : 0;
+ public boolean needsDeclaration() {
+ return (flags & NEEDS_DECLARATION) == NEEDS_DECLARATION;
}
/**
@@ -298,6 +346,16 @@ public abstract class Property implements Serializable {
}
/**
+ * Check if a flag is set for a property
+ * @param property property
+ * @param flag flag to check
+ * @return true if flag is set
+ */
+ public static boolean checkFlag(final Property property, final int flag) {
+ return (property.getFlags() & flag) == flag;
+ }
+
+ /**
* Get the flags for this property
* @return property flags
*/
@@ -361,6 +419,14 @@ public abstract class Property implements Serializable {
public abstract MethodHandle getGetter(final Class<?> type);
/**
+ * Get an optimistic getter that throws an exception if type is not the known given one
+ * @param type type
+ * @param programPoint program point
+ * @return getter
+ */
+ public abstract MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint);
+
+ /**
* Hook to initialize method handles after deserialization.
*
* @param structure the structure class
@@ -384,6 +450,46 @@ public abstract class Property implements Serializable {
}
/**
+ * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+ * getter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner of the property
+ * @return the property value
+ */
+ public abstract int getIntValue(final ScriptObject self, final ScriptObject owner);
+
+ /**
+ * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+ * getter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner of the property
+ * @return the property value
+ */
+ public abstract long getLongValue(final ScriptObject self, final ScriptObject owner);
+
+ /**
+ * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+ * getter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner of the property
+ * @return the property value
+ */
+ public abstract double getDoubleValue(final ScriptObject self, final ScriptObject owner);
+
+ /**
+ * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+ * getter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner of the property
+ * @return the property value
+ */
+ public abstract Object getObjectValue(final ScriptObject self, final ScriptObject owner);
+
+ /**
* Set the value of this property in {@code owner}. This allows to bypass creation of the
* setter MethodHandle for spill and user accessor properties.
*
@@ -392,17 +498,40 @@ public abstract class Property implements Serializable {
* @param value the new property value
* @param strict is this a strict setter?
*/
- public abstract void setObjectValue(ScriptObject self, ScriptObject owner, Object value, boolean strict);
+ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict);
/**
- * Set the Object value of this property from {@code owner}. This allows to bypass creation of the
- * getter MethodHandle for spill and user accessor properties.
+ * Set the value of this property in {@code owner}. This allows to bypass creation of the
+ * setter MethodHandle for spill and user accessor properties.
*
* @param self the this object
* @param owner the owner object
- * @return the property value
+ * @param value the new property value
+ * @param strict is this a strict setter?
+ */
+ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict);
+
+ /**
+ * Set the value of this property in {@code owner}. This allows to bypass creation of the
+ * setter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner object
+ * @param value the new property value
+ * @param strict is this a strict setter?
+ */
+ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict);
+
+ /**
+ * Set the value of this property in {@code owner}. This allows to bypass creation of the
+ * setter MethodHandle for spill and user accessor properties.
+ *
+ * @param self the this object
+ * @param owner the owner object
+ * @param value the new property value
+ * @param strict is this a strict setter?
*/
- public abstract Object getObjectValue(ScriptObject self, ScriptObject owner);
+ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict);
/**
* Abstract method for retrieving the setter for the property. We do not know
@@ -417,7 +546,7 @@ public abstract class Property implements Serializable {
* <p>
* see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
* if you are interested in the internal details of this. Note that if you
- * are running in default mode, with {@code -Dnashorn.fields.dual=true}, disabled, the setters
+ * are running with {@code -Dnashorn.fields.objects=true}, the setters
* will currently never change, as all properties are represented as Object field,
* the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
* boxed/unboxed upon every access, which is not necessarily optimal
@@ -450,7 +579,7 @@ public abstract class Property implements Serializable {
@Override
public int hashCode() {
- final Class<?> type = getCurrentType();
+ final Class<?> type = getLocalType();
return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
}
@@ -466,88 +595,119 @@ public abstract class Property implements Serializable {
final Property otherProperty = (Property)other;
- return getFlags() == otherProperty.getFlags() &&
- getSlot() == otherProperty.getSlot() &&
- getCurrentType() == otherProperty.getCurrentType() &&
- getKey().equals(otherProperty.getKey());
+ return equalsWithoutType(otherProperty) &&
+ getLocalType() == otherProperty.getLocalType();
}
+ boolean equalsWithoutType(final Property otherProperty) {
+ return getFlags() == otherProperty.getFlags() &&
+ getSlot() == otherProperty.getSlot() &&
+ getKey().equals(otherProperty.getKey());
+ }
+
+ private static final String type(final Class<?> type) {
+ if (type == null) {
+ return "undef";
+ } else if (type == int.class) {
+ return "i";
+ } else if (type == long.class) {
+ return "j";
+ } else if (type == double.class) {
+ return "d";
+ } else {
+ return "o";
+ }
+ }
+
+ /**
+ * Short toString version
+ * @return short toString
+ */
+ public final String toStringShort() {
+ final StringBuilder sb = new StringBuilder();
+ final Class<?> type = getLocalType();
+ sb.append(getKey()).append(" (").append(type(type)).append(')');
+ return sb.toString();
+ }
+
+ private static String indent(final String str, final int indent) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(str);
+ for (int i = 0; i < indent - str.length(); i++) {
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- final Class<?> type = getCurrentType();
+ final Class<?> type = getLocalType();
- sb.append(getKey()).
- append("(0x").
- append(Integer.toHexString(flags)).
+ sb.append(indent(getKey(), 20)).
+ append(" id=").
+ append(Debug.id(this)).
+ append(" (0x").
+ append(indent(Integer.toHexString(flags), 4)).
append(") ").
append(getClass().getSimpleName()).
append(" {").
- append(type == null ? "UNDEFINED" : Type.typeFor(type).getDescriptor()).
+ append(indent(type(type), 5)).
append('}');
if (slot != -1) {
- sb.append('[');
- sb.append(slot);
- sb.append(']');
+ sb.append(" [").
+ append("slot=").
+ append(slot).
+ append(']');
}
return sb.toString();
}
/**
- * Get the current type of this field. If you are not running with dual fields enabled,
+ * Get the current type of this property. If you are running with object fields enabled,
* this will always be Object.class. See the value representation explanation in
* {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
* for more information.
*
+ * <p>Note that for user accessor properties, this returns the type of the last observed
+ * value passed to or returned by a user accessor. Use {@link #getLocalType()} to always get
+ * the type of the actual value stored in the property slot.</p>
+ *
* @return current type of property, null means undefined
*/
- public Class<?> getCurrentType() {
- return Object.class;
+ public final Class<?> getType() {
+ return type;
}
/**
- * Check whether this Property can ever change its type. The default is false, and if
- * you are not running with dual fields, the type is always object and can never change
- * @return true if this property can change types
+ * Set the type of this property.
+ * @param type new type
*/
- public boolean canChangeType() {
- return false;
+ public final void setType(final Class<?> type) {
+ assert type != boolean.class : "no boolean storage support yet - fix this";
+ this.type = type == null ? null : type.isPrimitive() ? type : Object.class;
}
/**
- * Check whether this Property is ever used as anything but an Object. If this is used only
- * as an object, dual fields mode need not even try to represent it as a primitive at any
- * callsite, saving map rewrites for performance.
+ * Get the type of the value in the local property slot. This returns the same as
+ * {@link #getType()} for normal properties, but always returns {@code Object.class}
+ * for {@link UserAccessorProperty}s as their local type is a pair of accessor references.
*
- * @return true if representation should always be an object field
+ * @return the local property type
*/
- public boolean isAlwaysObject() {
- return (flags & IS_ALWAYS_OBJECT) == IS_ALWAYS_OBJECT;
+ protected Class<?> getLocalType() {
+ return getType();
}
/**
- * Check whether this property can be primitive. This is a conservative
- * analysis result, so {@code false} might mean that it can still be
- * primitive
- *
- * @return can be primitive status
- */
- public boolean canBePrimitive() {
- return (flags & CAN_BE_PRIMITIVE) == CAN_BE_PRIMITIVE;
- }
-
- /**
- * Check whether this property can be primitive. This is a conservative
- * analysis result, so {@code true} might mean that it can still be
- * defined, but it will never say that a property can not be undefined
- * if it can
- *
- * @return can be undefined status
+ * Check whether this Property can ever change its type. The default is false, and if
+ * you are not running with dual fields, the type is always object and can never change
+ * @return true if this property can change types
*/
- public boolean canBeUndefined() {
- return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED;
+ public boolean canChangeType() {
+ return false;
}
/**
@@ -557,4 +717,12 @@ public abstract class Property implements Serializable {
public boolean isFunctionDeclaration() {
return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
}
+
+ /**
+ * Is this a property defined by ES6 let or const?
+ * @return true if this property represents a lexical binding.
+ */
+ public boolean isLexicalBinding() {
+ return (flags & IS_LEXICAL_BINDING) == IS_LEXICAL_BINDING;
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyAccess.java b/src/jdk/nashorn/internal/runtime/PropertyAccess.java
index 165344ce..420ef44f 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyAccess.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyAccess.java
@@ -38,86 +38,98 @@ public interface PropertyAccess {
/**
* Get the value for a given key and return it as an int
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public int getInt(Object key);
+ public int getInt(Object key, int programPoint);
/**
* Get the value for a given key and return it as an int
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public int getInt(double key);
+ public int getInt(double key, int programPoint);
/**
* Get the value for a given key and return it as an int
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public int getInt(final long key);
+ public int getInt(long key, int programPoint);
/**
* Get the value for a given key and return it as an int
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public int getInt(int key);
+ public int getInt(int key, int programPoint);
/**
* Get the value for a given key and return it as a long
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public long getLong(Object key);
+ public long getLong(Object key, int programPoint);
/**
* Get the value for a given key and return it as a long
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public long getLong(double key);
+ public long getLong(double key, int programPoint);
/**
* Get the value for a given key and return it as a long
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public long getLong(long key);
+ public long getLong(long key, int programPoint);
/**
* Get the value for a given key and return it as a long
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public long getLong(int key);
+ public long getLong(int key, int programPoint);
/**
* Get the value for a given key and return it as a double
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public double getDouble(Object key);
+ public double getDouble(Object key, int programPoint);
/**
* Get the value for a given key and return it as a double
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public double getDouble(double key);
+ public double getDouble(double key, int programPoint);
/**
* Get the value for a given key and return it as a double
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public double getDouble(long key);
+ public double getDouble(long key, int programPoint);
/**
* Get the value for a given key and return it as a double
* @param key the key
+ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public double getDouble(int key);
+ public double getDouble(int key, int programPoint);
/**
* Get the value for a given key and return it as an Object
@@ -151,129 +163,129 @@ public interface PropertyAccess {
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(Object key, int value, boolean strict);
+ public void set(Object key, int value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(Object key, long value, boolean strict);
+ public void set(Object key, long value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(Object key, double value, boolean strict);
+ public void set(Object key, double value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(Object key, Object value, boolean strict);
+ public void set(Object key, Object value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(double key, int value, boolean strict);
+ public void set(double key, int value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(double key, long value, boolean strict);
+ public void set(double key, long value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(double key, double value, boolean strict);
+ public void set(double key, double value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(double key, Object value, boolean strict);
+ public void set(double key, Object value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(long key, int value, boolean strict);
+ public void set(long key, int value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(long key, long value, boolean strict);
+ public void set(long key, long value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(long key, double value, boolean strict);
+ public void set(long key, double value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(long key, Object value, boolean strict);
+ public void set(long key, Object value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(int key, int value, boolean strict);
+ public void set(int key, int value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(int key, long value, boolean strict);
+ public void set(int key, long value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(int key, double value, boolean strict);
+ public void set(int key, double value, int flags);
/**
* Set the value of a given key
* @param key the key
* @param value the value
- * @param strict are we in strict mode
+ * @param flags call site flags
*/
- public void set(int key, Object value, boolean strict);
+ public void set(int key, Object value, int flags);
/**
* Check if the given key exists anywhere in the proto chain
diff --git a/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java b/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
index f36bd45e..e00759ba 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
@@ -154,8 +154,8 @@ public interface PropertyDescriptor {
/**
* Check existence and compare attributes of descriptors.
- *
- * @return true if every field of this desc exists in otherDesc and has the same value.
+ * @param otherDesc other descriptor to compare to
+ * @return true if every field of this descriptor exists in otherDesc and has the same value.
*/
public boolean hasAndEquals(PropertyDescriptor otherDesc);
}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
index bfa06920..ba64af32 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
@@ -164,6 +164,19 @@ public final class PropertyHashMap implements Map <String, Property> {
}
/**
+ * Clone a property map, replacing a property with a new one in the same place,
+ * which is important for property iterations if a property changes types
+ * @param property old property
+ * @param newProperty new property
+ * @return new property map
+ */
+ public PropertyHashMap immutableReplace(final Property property, final Property newProperty) {
+ assert property.getKey().equals(newProperty.getKey()) : "replacing properties with different keys: '" + property.getKey() + "' != '" + newProperty.getKey() + "'";
+ assert findElement(property.getKey()) != null : "replacing property that doesn't exist in map: '" + property.getKey() + "'";
+ return cloneMap().replaceNoClone(property.getKey(), newProperty);
+ }
+
+ /**
* Clone a {@link PropertyHashMap} and add a {@link Property}.
*
* @param property {@link Property} to add.
@@ -289,7 +302,7 @@ public final class PropertyHashMap implements Map <String, Property> {
* @return The bin index.
*/
private static int binIndex(final Element[] bins, final String key) {
- return key.hashCode() & (bins.length - 1);
+ return key.hashCode() & bins.length - 1;
}
/**
@@ -301,7 +314,7 @@ public final class PropertyHashMap implements Map <String, Property> {
*/
private static int binsNeeded(final int n) {
// 50% padding
- return 1 << (32 - Integer.numberOfLeadingZeros((n + (n >>> 1)) | (INITIAL_BINS - 1)));
+ return 1 << 32 - Integer.numberOfLeadingZeros(n + (n >>> 1) | INITIAL_BINS - 1);
}
/**
@@ -327,8 +340,9 @@ public final class PropertyHashMap implements Map <String, Property> {
final Element[] newBins = new Element[binSize];
for (Element element = list; element != null; element = element.getLink()) {
final Property property = element.getProperty();
- final String key = property.getKey();
- final int binIndex = binIndex(newBins, key);
+ final String key = property.getKey();
+ final int binIndex = binIndex(newBins, key);
+
newBins[binIndex] = new Element(newBins[binIndex], property);
}
return newBins;
@@ -366,6 +380,11 @@ public final class PropertyHashMap implements Map <String, Property> {
return null;
}
+
+ private PropertyHashMap cloneMap() {
+ return new PropertyHashMap(size, bins == null ? null : bins.clone(), list);
+ }
+
/**
* Clone {@link PropertyHashMap} to accommodate new size.
*
@@ -385,6 +404,8 @@ public final class PropertyHashMap implements Map <String, Property> {
return new PropertyHashMap(newSize, newBins, list);
}
+
+
/**
* Add a {@link Property} to a temporary {@link PropertyHashMap}, that has
* been already cloned. Removes duplicates if necessary.
@@ -416,6 +437,18 @@ public final class PropertyHashMap implements Map <String, Property> {
return new PropertyHashMap(newSize, bins, newList);
}
+ private PropertyHashMap replaceNoClone(final String key, final Property property) {
+ if (bins != null) {
+ final int binIndex = binIndex(bins, key);
+ Element bin = bins[binIndex];
+ bin = replaceInList(bin, key, property);
+ bins[binIndex] = bin;
+ }
+ Element newList = list;
+ newList = replaceInList(newList, key, property);
+ return new PropertyHashMap(size, bins, newList);
+ }
+
/**
* Removes an {@link Element} from a specific list, avoiding duplication.
*
@@ -446,6 +479,30 @@ public final class PropertyHashMap implements Map <String, Property> {
return list;
}
+ // for element x. if x get link matches,
+ private static Element replaceInList(final Element list, final String key, final Property property) {
+ assert list != null;
+ final int hashCode = key.hashCode();
+
+ if (list.match(key, hashCode)) {
+ return new Element(list.getLink(), property);
+ }
+
+ final Element head = new Element(null, list.getProperty());
+ Element previous = head;
+ for (Element element = list.getLink(); element != null; element = element.getLink()) {
+ if (element.match(key, hashCode)) {
+ previous.setLink(new Element(element.getLink(), property));
+ return head;
+ }
+ final Element next = new Element(null, element.getProperty());
+ previous.setLink(next);
+ previous = next;
+ }
+ return list;
+ }
+
+
/*
* Map implementation
*/
@@ -617,6 +674,26 @@ public final class PropertyHashMap implements Map <String, Property> {
throw new UnsupportedOperationException("Immutable map.");
}
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer();
+
+ sb.append('[');
+
+ Element elem = this;
+ do {
+ sb.append(elem.getValue());
+ elem = elem.link;
+ if (elem != null) {
+ sb.append(" -> ");
+ }
+ } while (elem != null);
+
+ sb.append(']');
+
+ return sb.toString();
+ }
+
/*
* Accessors
*/
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
index 532969cc..03b2c93a 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyListeners.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@@ -111,7 +111,7 @@ public class PropertyListeners {
if (listeners == null) {
return false;
}
- WeakPropertyMapSet set = listeners.get(key);
+ final WeakPropertyMapSet set = listeners.get(key);
return set != null && set.contains(propertyMap);
}
@@ -145,9 +145,9 @@ public class PropertyListeners {
*/
public synchronized void propertyAdded(final Property prop) {
if (listeners != null) {
- WeakPropertyMapSet set = listeners.get(prop.getKey());
+ final WeakPropertyMapSet set = listeners.get(prop.getKey());
if (set != null) {
- for (PropertyMap propertyMap : set.elements()) {
+ for (final PropertyMap propertyMap : set.elements()) {
propertyMap.propertyAdded(prop);
}
listeners.remove(prop.getKey());
@@ -162,9 +162,9 @@ public class PropertyListeners {
*/
public synchronized void propertyDeleted(final Property prop) {
if (listeners != null) {
- WeakPropertyMapSet set = listeners.get(prop.getKey());
+ final WeakPropertyMapSet set = listeners.get(prop.getKey());
if (set != null) {
- for (PropertyMap propertyMap : set.elements()) {
+ for (final PropertyMap propertyMap : set.elements()) {
propertyMap.propertyDeleted(prop);
}
listeners.remove(prop.getKey());
@@ -181,9 +181,9 @@ public class PropertyListeners {
*/
public synchronized void propertyModified(final Property oldProp, final Property newProp) {
if (listeners != null) {
- WeakPropertyMapSet set = listeners.get(oldProp.getKey());
+ final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
if (set != null) {
- for (PropertyMap propertyMap : set.elements()) {
+ for (final PropertyMap propertyMap : set.elements()) {
propertyMap.propertyModified(oldProp, newProp);
}
listeners.remove(oldProp.getKey());
@@ -191,10 +191,13 @@ public class PropertyListeners {
}
}
+ /**
+ * Callback for when a proto is changed
+ */
public synchronized void protoChanged() {
if (listeners != null) {
- for (WeakPropertyMapSet set : listeners.values()) {
- for (PropertyMap propertyMap : set.elements()) {
+ for (final WeakPropertyMapSet set : listeners.values()) {
+ for (final PropertyMap propertyMap : set.elements()) {
propertyMap.protoChanged();
}
}
@@ -204,7 +207,7 @@ public class PropertyListeners {
private static class WeakPropertyMapSet {
- private WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
+ private final WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
void add(final PropertyMap propertyMap) {
map.put(propertyMap, Boolean.TRUE);
diff --git a/src/jdk/nashorn/internal/runtime/PropertyMap.java b/src/jdk/nashorn/internal/runtime/PropertyMap.java
index e2e07fdf..30a15132 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -36,6 +36,7 @@ import java.io.Serializable;
import java.lang.invoke.SwitchPoint;
import java.lang.ref.SoftReference;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -68,7 +69,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
private int fieldCount;
/** Number of fields available. */
- private int fieldMaximum;
+ private final int fieldMaximum;
/** Length of spill in use. */
private int spillLength;
@@ -83,11 +84,13 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
/** History of prototypes, used to limit map duplication. */
- private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
+ private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
/** property listeners */
private transient PropertyListeners listeners;
+ private transient BitSet freeSlots;
+
private static final long serialVersionUID = -7041836752008732533L;
/**
@@ -129,6 +132,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
this.fieldMaximum = propertyMap.fieldMaximum;
// We inherit the parent property listeners instance. It will be cloned when a new listener is added.
this.listeners = propertyMap.listeners;
+ this.freeSlots = propertyMap.freeSlots;
if (Context.DEBUG) {
count++;
@@ -145,21 +149,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
this(propertyMap, propertyMap.properties);
}
- /**
- * Duplicates this PropertyMap instance. This is used to duplicate 'shared'
- * maps {@link PropertyMap} used as process wide singletons. Shared maps are
- * duplicated for every global scope object. That way listeners, proto and property
- * histories are scoped within a global scope.
- *
- * @return Duplicated {@link PropertyMap}.
- */
- public PropertyMap duplicate() {
- if (Context.DEBUG) {
- duplicatedCount++;
- }
- return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
- }
-
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(properties.getProperties());
@@ -173,7 +162,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
assert className != null;
final Class<?> structure = Context.forStructureClass(className);
- for (Property prop : props) {
+ for (final Property prop : props) {
prop.initMethodHandles(structure);
}
}
@@ -185,13 +174,14 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* properties with keys that are valid array indices.</p>
*
* @param properties Collection of initial properties.
+ * @param className class name
* @param fieldCount Number of fields in use.
* @param fieldMaximum Number of fields available.
* @param spillLength Number of used spill slots.
* @return New {@link PropertyMap}.
*/
public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum, final int spillLength) {
- PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
+ final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
}
@@ -205,7 +195,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* @return New {@link PropertyMap}.
*/
public static PropertyMap newMap(final Collection<Property> properties) {
- return (properties == null || properties.isEmpty())? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
+ return properties == null || properties.isEmpty()? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
}
/**
@@ -364,6 +354,51 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
return addPropertyNoHistory(new AccessorProperty(property, bindTo));
}
+ // Get a logical slot index for a property, with spill slot 0 starting at fieldMaximum.
+ private int logicalSlotIndex(final Property property) {
+ final int slot = property.getSlot();
+ if (slot < 0) {
+ return -1;
+ }
+ return property.isSpill() ? slot + fieldMaximum : slot;
+ }
+
+ // Update boundaries and flags after a property has been added
+ private void updateFlagsAndBoundaries(final Property newProperty) {
+ if(newProperty.isSpill()) {
+ spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
+ } else {
+ fieldCount = Math.max(fieldCount, newProperty.getSlot() + 1);
+ }
+ if (isValidArrayIndex(getArrayIndex(newProperty.getKey()))) {
+ setContainsArrayKeys();
+ }
+ }
+
+ // Update the free slots bitmap for a property that has been deleted and/or added.
+ private void updateFreeSlots(final Property oldProperty, final Property newProperty) {
+ // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications.
+ boolean freeSlotsCloned = false;
+ if (oldProperty != null) {
+ final int slotIndex = logicalSlotIndex(oldProperty);
+ if (slotIndex >= 0) {
+ final BitSet newFreeSlots = freeSlots == null ? new BitSet() : (BitSet)freeSlots.clone();
+ assert !newFreeSlots.get(slotIndex);
+ newFreeSlots.set(slotIndex);
+ freeSlots = newFreeSlots;
+ freeSlotsCloned = true;
+ }
+ }
+ if (freeSlots != null && newProperty != null) {
+ final int slotIndex = logicalSlotIndex(newProperty);
+ if (slotIndex > -1 && freeSlots.get(slotIndex)) {
+ final BitSet newFreeSlots = freeSlotsCloned ? freeSlots : ((BitSet)freeSlots.clone());
+ newFreeSlots.clear(slotIndex);
+ freeSlots = newFreeSlots.isEmpty() ? null : newFreeSlots;
+ }
+ }
+ }
+
/**
* Add a property to the map without adding it to the history. This should be used for properties that
* can't be shared such as bound properties, or properties that are expected to be added only once.
@@ -377,15 +412,9 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
}
final PropertyHashMap newProperties = properties.immutableAdd(property);
final PropertyMap newMap = new PropertyMap(this, newProperties);
+ newMap.updateFlagsAndBoundaries(property);
+ newMap.updateFreeSlots(null, property);
- if(!property.isSpill()) {
- newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
- }
- if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
- newMap.setContainsArrayKeys();
- }
-
- newMap.spillLength += property.getSpillCount();
return newMap;
}
@@ -406,15 +435,8 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
final PropertyHashMap newProperties = properties.immutableAdd(property);
newMap = new PropertyMap(this, newProperties);
addToHistory(property, newMap);
-
- if(!property.isSpill()) {
- newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
- }
- if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
- newMap.setContainsArrayKeys();
- }
-
- newMap.spillLength += property.getSpillCount();
+ newMap.updateFlagsAndBoundaries(property);
+ newMap.updateFreeSlots(null, property);
}
return newMap;
@@ -436,7 +458,20 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
if (newMap == null && properties.containsKey(key)) {
final PropertyHashMap newProperties = properties.immutableRemove(key);
- newMap = new PropertyMap(this, newProperties);
+ final boolean isSpill = property.isSpill();
+ final int slot = property.getSlot();
+ // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
+ // Otherwise mark it as free in free slots bitset.
+ if (isSpill && slot >= 0 && slot == spillLength - 1) {
+ newMap = new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength - 1, containsArrayKeys());
+ newMap.freeSlots = freeSlots;
+ } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
+ newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
+ newMap.freeSlots = freeSlots;
+ } else {
+ newMap = new PropertyMap(this, newProperties);
+ newMap.updateFreeSlots(property, null);
+ }
addToHistory(property, newMap);
}
@@ -456,9 +491,8 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
listeners.propertyModified(oldProperty, newProperty);
}
// Add replaces existing property.
- final PropertyHashMap newProperties = properties.immutableAdd(newProperty);
+ final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
final PropertyMap newMap = new PropertyMap(this, newProperties);
-
/*
* See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
*
@@ -474,10 +508,11 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* the old property is an AccessorProperty and the new one is a UserAccessorProperty property.
*/
- final boolean sameType = (oldProperty.getClass() == newProperty.getClass());
+ final boolean sameType = oldProperty.getClass() == newProperty.getClass();
assert sameType ||
- (oldProperty instanceof AccessorProperty &&
- newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
+ oldProperty instanceof AccessorProperty &&
+ newProperty instanceof UserAccessorProperty :
+ "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
newMap.flags = flags;
@@ -485,7 +520,10 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
* to add spill count of the newly added UserAccessorProperty property.
*/
- newMap.spillLength = spillLength + (sameType? 0 : newProperty.getSpillCount());
+ if (!sameType) {
+ newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
+ newMap.updateFreeSlots(oldProperty, newProperty);
+ }
return newMap;
}
@@ -500,12 +538,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* @return the newly created UserAccessorProperty
*/
public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
- int oldSpillLength = spillLength;
-
- final int getterSlot = oldSpillLength++;
- final int setterSlot = oldSpillLength++;
-
- return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
+ return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
}
/**
@@ -533,10 +566,9 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
final PropertyMap newMap = new PropertyMap(this, newProperties);
for (final Property property : otherProperties) {
- if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
- newMap.setContainsArrayKeys();
- }
- newMap.spillLength += property.getSpillCount();
+ // This method is only safe to use with non-slotted, native getter/setter properties
+ assert property.getSlot() == -1;
+ assert !(isValidArrayIndex(getArrayIndex(property.getKey())));
}
return newMap;
@@ -590,7 +622,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
PropertyMap freeze() {
PropertyHashMap newProperties = EMPTY_HASHMAP;
- for (Property oldProperty : properties.getProperties()) {
+ for (final Property oldProperty : properties.getProperties()) {
int propertyFlags = Property.NOT_CONFIGURABLE;
if (!(oldProperty instanceof UserAccessorProperty)) {
@@ -645,14 +677,14 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
/**
* Check prototype history for an existing property map with specified prototype.
*
- * @param parentMap New prototype object.
+ * @param proto New prototype object.
*
* @return Existing {@link PropertyMap} or {@code null} if not found.
*/
- private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
+ private PropertyMap checkProtoHistory(final ScriptObject proto) {
final PropertyMap cachedMap;
if (protoHistory != null) {
- final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
+ final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
cachedMap = (weakMap != null ? weakMap.get() : null);
} else {
cachedMap = null;
@@ -668,15 +700,15 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
/**
* Add a map to the prototype history.
*
- * @param parentMap Prototype to add (key.)
+ * @param newProto Prototype to add (key.)
* @param newMap {@link PropertyMap} associated with prototype.
*/
- private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
+ private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
if (protoHistory == null) {
protoHistory = new WeakHashMap<>();
}
- protoHistory.put(parentMap, new SoftReference<>(newMap));
+ protoHistory.put(newProto, new SoftReference<>(newMap));
}
/**
@@ -686,13 +718,11 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* @param newMap Modified {@link PropertyMap}.
*/
private void addToHistory(final Property property, final PropertyMap newMap) {
- if (!properties.isEmpty()) {
- if (history == null) {
- history = new WeakHashMap<>();
- }
-
- history.put(property, new SoftReference<>(newMap));
+ if (history == null) {
+ history = new WeakHashMap<>();
}
+
+ history.put(property, new SoftReference<>(newMap));
}
/**
@@ -705,7 +735,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
private PropertyMap checkHistory(final Property property) {
if (history != null) {
- SoftReference<PropertyMap> ref = history.get(property);
+ final SoftReference<PropertyMap> ref = history.get(property);
final PropertyMap historicMap = ref == null ? null : ref.get();
if (historicMap != null) {
@@ -720,32 +750,44 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
return null;
}
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
+ /**
+ * Returns true if the two maps have identical properties in the same order, but allows the properties to differ in
+ * their types. This method is mostly useful for tests.
+ * @param otherMap the other map
+ * @return true if this map has identical properties in the same order as the other map, allowing the properties to
+ * differ in type.
+ */
+ public boolean equalsWithoutType(final PropertyMap otherMap) {
+ if (properties.size() != otherMap.properties.size()) {
+ return false;
+ }
- sb.append(" [");
- boolean isFirst = true;
+ final Iterator<Property> iter = properties.values().iterator();
+ final Iterator<Property> otherIter = otherMap.properties.values().iterator();
- for (final Property property : properties.values()) {
- if (!isFirst) {
- sb.append(", ");
+ while (iter.hasNext() && otherIter.hasNext()) {
+ if (!iter.next().equalsWithoutType(otherIter.next())) {
+ return false;
}
+ }
+
+ return true;
+ }
- isFirst = false;
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
- sb.append(ScriptRuntime.safeToString(property.getKey()));
- final Class<?> ctype = property.getCurrentType();
- sb.append(" <").
- append(property.getClass().getSimpleName()).
- append(':').
- append(ctype == null ?
- "undefined" :
- ctype.getSimpleName()).
- append('>');
+ sb.append(Debug.id(this));
+ sb.append(" = {\n");
+
+ for (final Property property : getProperties()) {
+ sb.append('\t');
+ sb.append(property);
+ sb.append('\n');
}
- sb.append(']');
+ sb.append('}');
return sb.toString();
}
@@ -799,29 +841,37 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
boolean isFrozen() {
return !isExtensible() && allFrozen();
}
+
/**
- * Get the number of fields allocated for this {@link PropertyMap}.
- *
- * @return Number of fields allocated.
- */
- int getFieldCount() {
- return fieldCount;
- }
- /**
- * Get maximum number of fields available for this {@link PropertyMap}.
+ * Return a free field slot for this map, or {@code -1} if none is available.
*
- * @return Number of fields available.
+ * @return free field slot or -1
*/
- int getFieldMaximum() {
- return fieldMaximum;
+ int getFreeFieldSlot() {
+ if (freeSlots != null) {
+ final int freeSlot = freeSlots.nextSetBit(0);
+ if (freeSlot > -1 && freeSlot < fieldMaximum) {
+ return freeSlot;
+ }
+ }
+ if (fieldCount < fieldMaximum) {
+ return fieldCount;
+ }
+ return -1;
}
/**
- * Get length of spill area associated with this {@link PropertyMap}.
+ * Get a free spill slot for this map.
*
- * @return Length of spill area.
+ * @return free spill slot
*/
- int getSpillLength() {
+ int getFreeSpillSlot() {
+ if (freeSlots != null) {
+ final int freeSlot = freeSlots.nextSetBit(fieldMaximum);
+ if (freeSlot > -1) {
+ return freeSlot - fieldMaximum;
+ }
+ }
return spillLength;
}
@@ -833,8 +883,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
*/
public PropertyMap changeProto(final ScriptObject newProto) {
- final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
- final PropertyMap nextMap = checkProtoHistory(parentMap);
+ final PropertyMap nextMap = checkProtoHistory(newProto);
if (nextMap != null) {
return nextMap;
}
@@ -844,7 +893,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
}
final PropertyMap newMap = new PropertyMap(this);
- addToProtoHistory(parentMap, newMap);
+ addToProtoHistory(newProto, newMap);
return newMap;
}
@@ -900,7 +949,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
@Override
public void remove() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("remove");
}
}
@@ -908,10 +957,60 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
* Debugging and statistics.
*/
+ /**
+ * Debug helper function that returns the diff of two property maps, only
+ * displaying the information that is different and in which map it exists
+ * compared to the other map. Can be used to e.g. debug map guards and
+ * investigate why they fail, causing relink
+ *
+ * @param map0 the first property map
+ * @param map1 the second property map
+ *
+ * @return property map diff as string
+ */
+ public static String diff(final PropertyMap map0, final PropertyMap map1) {
+ final StringBuilder sb = new StringBuilder();
+
+ if (map0 != map1) {
+ sb.append(">>> START: Map diff");
+ boolean found = false;
+
+ for (final Property p : map0.getProperties()) {
+ final Property p2 = map1.findProperty(p.getKey());
+ if (p2 == null) {
+ sb.append("FIRST ONLY : [" + p + "]");
+ found = true;
+ } else if (p2 != p) {
+ sb.append("DIFFERENT : [" + p + "] != [" + p2 + "]");
+ found = true;
+ }
+ }
+
+ for (final Property p2 : map1.getProperties()) {
+ final Property p1 = map0.findProperty(p2.getKey());
+ if (p1 == null) {
+ sb.append("SECOND ONLY: [" + p2 + "]");
+ found = true;
+ }
+ }
+
+ //assert found;
+
+ if (!found) {
+ sb.append(map0).
+ append("!=").
+ append(map1);
+ }
+
+ sb.append("<<< END: Map diff\n");
+ }
+
+ return sb.toString();
+ }
+
// counters updated only in debug mode
private static int count;
private static int clonedCount;
- private static int duplicatedCount;
private static int historyHit;
private static int protoInvalidations;
private static int protoHistoryHit;
@@ -932,13 +1031,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
}
/**
- * @return The number of maps that are duplicated.
- */
- public static int getDuplicatedCount() {
- return duplicatedCount;
- }
-
- /**
* @return The number of times history was successfully used.
*/
public static int getHistoryHit() {
@@ -965,5 +1057,4 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
public static int getSetProtoNewMapCount() {
return setProtoNewMapCount;
}
-
}
diff --git a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index 90885444..06414edb 100644
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,106 +26,233 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
-
-import java.io.Serializable;
+import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.Namespace;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
+import jdk.nashorn.internal.codegen.TypeMap;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.scripts.JS;
-
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* This is a subclass that represents a script function that may be regenerated,
* for example with specialization based on call site types, or lazily generated.
* The common denominator is that it can get new invokers during its lifespan,
* unlike {@code FinalScriptFunctionData}
*/
-public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Serializable {
+@Logger(name="recompile")
+public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Loggable {
+ /** Prefix used for all recompiled script classes */
+ public static final String RECOMPILATION_PREFIX = "Recompilation$";
- /** FunctionNode with the code for this ScriptFunction */
- private transient FunctionNode functionNode;
+ /** Unique function node id for this function node */
+ private final int functionNodeId;
- /** Source from which FunctionNode was parsed. */
- private transient Source source;
+ private final String functionName;
/** The line number where this function begins. */
private final int lineNumber;
- /** Allows us to retrieve the method handle for this function once the code is compiled */
- private MethodLocator methodLocator;
+ /** Source from which FunctionNode was parsed. */
+ private transient Source source;
+
+ /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */
+ private final byte[] serializedAst;
/** Token of this function within the source. */
private final long token;
- /** Allocator map from makeMap() */
- private final PropertyMap allocatorMap;
+ /**
+ * Represents the allocation strategy (property map, script object class, and method handle) for when
+ * this function is used as a constructor. Note that majority of functions (those not setting any this.*
+ * properties) will share a single canonical "default strategy" instance.
+ */
+ private final AllocationStrategy allocationStrategy;
+
+ /**
+ * Opaque object representing parser state at the end of the function. Used when reparsing outer function
+ * to help with skipping parsing inner functions.
+ */
+ private final Object endParserState;
/** Code installer used for all further recompilation/specialization of this ScriptFunction */
private transient CodeInstaller<ScriptEnvironment> installer;
- /** Name of class where allocator function resides */
- private final String allocatorClassName;
+ private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
- /** lazily generated allocator */
- private transient MethodHandle allocator;
+ /** Id to parent function if one exists */
+ private RecompilableScriptFunctionData parent;
+
+ /** Copy of the {@link FunctionNode} flags. */
+ private final int functionFlags;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
- /**
- * Used for specialization based on runtime arguments. Whenever we specialize on
- * callsite parameter types at runtime, we need to use a parameter type guard to
- * ensure that the specialized version of the script function continues to be
- * applicable for a particular callsite.
- */
- private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Object[].class);
+ private transient DebugLogger log;
- /**
- * It is usually a good gamble whever we detect a runtime callsite with a double
- * (or java.lang.Number instance) to specialize the parameter to an integer, if the
- * parameter in question can be represented as one. The double typically only exists
- * because the compiler doesn't know any better than "a number type" and conservatively
- * picks doubles when it can't prove that an integer addition wouldn't overflow.
- */
- private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
+ private final Map<String, Integer> externalScopeDepths;
+
+ private final Set<String> internalSymbols;
+
+ private static final int GET_SET_PREFIX_LENGTH = "*et ".length();
private static final long serialVersionUID = 4914839316174633726L;
/**
* Constructor - public as scripts use it
*
- * @param functionNode functionNode that represents this function code
- * @param installer installer for code regeneration versions of this function
- * @param allocatorClassName name of our allocator class, will be looked up dynamically if used as a constructor
- * @param allocatorMap allocator map to seed instances with, when constructing
+ * @param functionNode functionNode that represents this function code
+ * @param installer installer for code regeneration versions of this function
+ * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor
+ * @param nestedFunctions nested function map
+ * @param externalScopeDepths external scope depths
+ * @param internalSymbols internal symbols to method, defined in its scope
+ * @param serializedAst a serialized AST representation. Normally only used for split functions.
*/
- public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
+ public RecompilableScriptFunctionData(
+ final FunctionNode functionNode,
+ final CodeInstaller<ScriptEnvironment> installer,
+ final AllocatorDescriptor allocationDescriptor,
+ final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
+ final Map<String, Integer> externalScopeDepths,
+ final Set<String> internalSymbols,
+ final byte[] serializedAst) {
+
super(functionName(functionNode),
- functionNode.getParameters().size(),
- getFlags(functionNode));
- this.functionNode = functionNode;
- this.source = functionNode.getSource();
- this.lineNumber = functionNode.getLineNumber();
- this.token = tokenFor(functionNode);
- this.installer = installer;
- this.allocatorClassName = allocatorClassName;
- this.allocatorMap = allocatorMap;
- if (!functionNode.isLazy()) {
- methodLocator = new MethodLocator(functionNode);
+ Math.min(functionNode.getParameters().size(), MAX_ARITY),
+ getDataFlags(functionNode));
+
+ this.functionName = functionNode.getName();
+ this.lineNumber = functionNode.getLineNumber();
+ this.functionFlags = functionNode.getFlags() | (functionNode.needsCallee() ? FunctionNode.NEEDS_CALLEE : 0);
+ this.functionNodeId = functionNode.getId();
+ this.source = functionNode.getSource();
+ this.endParserState = functionNode.getEndParserState();
+ this.token = tokenFor(functionNode);
+ this.installer = installer;
+ this.allocationStrategy = AllocationStrategy.get(allocationDescriptor);
+ this.nestedFunctions = smallMap(nestedFunctions);
+ this.externalScopeDepths = smallMap(externalScopeDepths);
+ this.internalSymbols = smallSet(new HashSet<>(internalSymbols));
+
+ for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) {
+ assert nfn.getParent() == null;
+ nfn.setParent(this);
+ }
+
+ this.serializedAst = serializedAst;
+ createLogger();
+ }
+
+ private static <K, V> Map<K, V> smallMap(final Map<K, V> map) {
+ if (map == null || map.isEmpty()) {
+ return Collections.emptyMap();
+ } else if (map.size() == 1) {
+ final Map.Entry<K, V> entry = map.entrySet().iterator().next();
+ return Collections.singletonMap(entry.getKey(), entry.getValue());
+ } else {
+ return map;
}
}
+ private static <T> Set<T> smallSet(final Set<T> set) {
+ if (set == null || set.isEmpty()) {
+ return Collections.emptySet();
+ } else if (set.size() == 1) {
+ return Collections.singleton(set.iterator().next());
+ } else {
+ return set;
+ }
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context ctxt) {
+ return ctxt.getLogger(this.getClass());
+ }
+
+ /**
+ * Check if a symbol is internally defined in a function. For example
+ * if "undefined" is internally defined in the outermost program function,
+ * it has not been reassigned or overridden and can be optimized
+ *
+ * @param symbolName symbol name
+ * @return true if symbol is internal to this ScriptFunction
+ */
+
+ public boolean hasInternalSymbol(final String symbolName) {
+ return internalSymbols.contains(symbolName);
+ }
+
+ /**
+ * Return the external symbol table
+ * @param symbolName symbol name
+ * @return the external symbol table with proto depths
+ */
+ public int getExternalSymbolDepth(final String symbolName) {
+ final Integer depth = externalScopeDepths.get(symbolName);
+ return depth == null ? -1 : depth;
+ }
+
+ /**
+ * Returns the names of all external symbols this function uses.
+ * @return the names of all external symbols this function uses.
+ */
+ public Set<String> getExternalSymbolNames() {
+ return Collections.unmodifiableSet(externalScopeDepths.keySet());
+ }
+
+ /**
+ * Returns the opaque object representing the parser state at the end of this function's body, used to
+ * skip parsing this function when reparsing its containing outer function.
+ * @return the object representing the end parser state
+ */
+ public Object getEndParserState() {
+ return endParserState;
+ }
+
+ /**
+ * Get the parent of this RecompilableScriptFunctionData. If we are
+ * a nested function, we have a parent. Note that "null" return value
+ * can also mean that we have a parent but it is unknown, so this can
+ * only be used for conservative assumptions.
+ * @return parent data, or null if non exists and also null IF UNKNOWN.
+ */
+ public RecompilableScriptFunctionData getParent() {
+ return parent;
+ }
+
+ void setParent(final RecompilableScriptFunctionData parent) {
+ this.parent = parent;
+ }
+
@Override
String toSource() {
if (source != null && token != 0) {
@@ -135,46 +262,75 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
return "function " + (name == null ? "" : name) + "() { [native code] }";
}
- public void setCodeAndSource(final Map<String, Class<?>> code, final Source source) {
- this.source = source;
- if (methodLocator != null) {
- methodLocator.setClass(code.get(methodLocator.getClassName()));
+ /**
+ * Initialize transient fields on deserialized instances
+ *
+ * @param src source
+ * @param inst code installer
+ */
+ public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
+ if (this.source == null && this.installer == null) {
+ this.source = src;
+ this.installer = inst;
+ } else if (this.source != src || !this.installer.isCompatibleWith(inst)) {
+ // Existing values must be same as those passed as parameters
+ throw new IllegalArgumentException();
}
}
@Override
public String toString() {
+ return super.toString() + '@' + functionNodeId;
+ }
+
+ @Override
+ public String toStringVerbose() {
final StringBuilder sb = new StringBuilder();
+ sb.append("fnId=").append(functionNodeId).append(' ');
+
if (source != null) {
- sb.append(source.getName()).append(':').append(lineNumber).append(' ');
+ sb.append(source.getName())
+ .append(':')
+ .append(lineNumber)
+ .append(' ');
}
return sb.toString() + super.toString();
}
+ @Override
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ @Override
+ public boolean inDynamicContext() {
+ return getFunctionFlag(FunctionNode.IN_DYNAMIC_CONTEXT);
+ }
+
private static String functionName(final FunctionNode fn) {
if (fn.isAnonymous()) {
return "";
- } else {
- final FunctionNode.Kind kind = fn.getKind();
- if (kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
- final String name = NameCodec.decode(fn.getIdent().getName());
- return name.substring(4); // 4 is "get " or "set "
- } else {
- return fn.getIdent().getName();
- }
}
+ final FunctionNode.Kind kind = fn.getKind();
+ if (kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
+ final String name = NameCodec.decode(fn.getIdent().getName());
+ return name.substring(GET_SET_PREFIX_LENGTH);
+ }
+ return fn.getIdent().getName();
}
private static long tokenFor(final FunctionNode fn) {
- final int position = Token.descPosition(fn.getFirstToken());
- final int length = Token.descPosition(fn.getLastToken()) - position + Token.descLength(fn.getLastToken());
+ final int position = Token.descPosition(fn.getFirstToken());
+ final long lastToken = Token.withDelimiter(fn.getLastToken());
+ // EOL uses length field to store the line number
+ final int length = Token.descPosition(lastToken) - position + (Token.descType(lastToken) == TokenType.EOL ? 0 : Token.descLength(lastToken));
return Token.toDesc(TokenType.FUNCTION, position, length);
}
- private static int getFlags(final FunctionNode functionNode) {
+ private static int getDataFlags(final FunctionNode functionNode) {
int flags = IS_CONSTRUCTOR;
if (functionNode.isStrict()) {
flags |= IS_STRICT;
@@ -185,327 +341,540 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
if (functionNode.usesThis() || functionNode.hasEval()) {
flags |= USES_THIS;
}
+ if (functionNode.isVarArg()) {
+ flags |= IS_VARIABLE_ARITY;
+ }
return flags;
}
@Override
+ PropertyMap getAllocatorMap() {
+ return allocationStrategy.getAllocatorMap();
+ }
+
+ @Override
ScriptObject allocate(final PropertyMap map) {
- try {
- ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
- return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
- } catch (final RuntimeException | Error e) {
- throw e;
- } catch (final Throwable t) {
- throw new RuntimeException(t);
- }
+ return allocationStrategy.allocate(map);
}
- private void ensureHasAllocator() throws ClassNotFoundException {
- if (allocator == null && allocatorClassName != null) {
- this.allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName), CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
+ boolean isSerialized() {
+ return serializedAst != null;
+ }
+
+ FunctionNode reparse() {
+ if (isSerialized()) {
+ return deserialize();
+ }
+
+ final int descPosition = Token.descPosition(token);
+ final Context context = Context.getContextTrusted();
+ final Parser parser = new Parser(
+ context.getEnv(),
+ source,
+ new Context.ThrowErrorManager(),
+ isStrict(),
+ // source starts at line 0, so even though lineNumber is the correct declaration line, back off
+ // one to make it exclusive
+ lineNumber - 1,
+ context.getLogger(Parser.class));
+
+ if (getFunctionFlag(FunctionNode.IS_ANONYMOUS)) {
+ parser.setFunctionName(functionName);
+ }
+ parser.setReparsedFunction(this);
+
+ final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition,
+ Token.descLength(token), true);
+ // Parser generates a program AST even if we're recompiling a single function, so when we are only
+ // recompiling a single function, extract it from the program.
+ return (isProgram() ? program : extractFunctionFromScript(program)).setName(null, functionName);
+ }
+
+ private FunctionNode deserialize() {
+ final ScriptEnvironment env = installer.getOwner();
+ final Timing timing = env._timing;
+ final long t1 = System.nanoTime();
+ try {
+ return AstDeserializer.deserialize(serializedAst).initializeDeserialized(source, new Namespace(env.getNamespace()));
+ } finally {
+ timing.accumulateTime("'Deserialize'", System.nanoTime() - t1);
}
}
- @Override
- PropertyMap getAllocatorMap() {
- return allocatorMap;
+ private boolean getFunctionFlag(final int flag) {
+ return (functionFlags & flag) != 0;
}
+ private boolean isProgram() {
+ return getFunctionFlag(FunctionNode.IS_PROGRAM);
+ }
- @Override
- protected void ensureCompiled() {
- if (functionNode != null && functionNode.isLazy()) {
- Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
- final Compiler compiler = new Compiler(installer);
- functionNode = compiler.compile(functionNode);
- assert !functionNode.isLazy();
- compiler.install(functionNode);
- methodLocator = new MethodLocator(functionNode);
- flags = getFlags(functionNode);
+ TypeMap typeMap(final MethodType fnCallSiteType) {
+ if (fnCallSiteType == null) {
+ return null;
}
- if (functionNode != null) {
- methodLocator.setClass(functionNode.getCompileUnit().getCode());
+ if (CompiledFunction.isVarArgsType(fnCallSiteType)) {
+ return null;
}
+
+ return new TypeMap(functionNodeId, explicitParams(fnCallSiteType), needsCallee());
}
- @Override
- protected synchronized void ensureCodeGenerated() {
- if (!code.isEmpty()) {
- return; // nothing to do, we have code, at least some.
+ private static ScriptObject newLocals(final ScriptObject runtimeScope) {
+ final ScriptObject locals = Global.newEmptyInstance();
+ locals.setProto(runtimeScope);
+ return locals;
+ }
+
+ private Compiler getCompiler(final FunctionNode fn, final MethodType actualCallSiteType, final ScriptObject runtimeScope) {
+ return getCompiler(fn, actualCallSiteType, newLocals(runtimeScope), null, null);
+ }
+
+ /**
+ * Returns a code installer for installing new code. If we're using either optimistic typing or loader-per-compile,
+ * then asks for a code installer with a new class loader; otherwise just uses the current installer. We use
+ * a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC.
+ * @return a code installer for installing new code.
+ */
+ private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() {
+ final ScriptEnvironment env = installer.getOwner();
+ return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
+ }
+
+ Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType,
+ final ScriptObject runtimeScope, final Map<Integer, Type> invalidatedProgramPoints,
+ final int[] continuationEntryPoints) {
+ final TypeMap typeMap = typeMap(actualCallSiteType);
+ final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+ final Object typeInformationFile = OptimisticTypesPersistence.getLocationDescriptor(source, functionNodeId, paramTypes);
+ final Context context = Context.getContextTrusted();
+ return new Compiler(
+ context,
+ context.getEnv(),
+ getInstallerForNewCode(),
+ functionNode.getSource(), // source
+ context.getErrorManager(),
+ isStrict() | functionNode.isStrict(), // is strict
+ true, // is on demand
+ this, // compiledFunction, i.e. this RecompilableScriptFunctionData
+ typeMap, // type map
+ getEffectiveInvalidatedProgramPoints(invalidatedProgramPoints, typeInformationFile), // invalidated program points
+ typeInformationFile,
+ continuationEntryPoints, // continuation entry points
+ runtimeScope); // runtime scope
+ }
+
+ /**
+ * If the function being compiled already has its own invalidated program points map, use it. Otherwise, attempt to
+ * load invalidated program points map from the persistent type info cache.
+ * @param invalidatedProgramPoints the function's current invalidated program points map. Null if the function
+ * doesn't have it.
+ * @param typeInformationFile the object describing the location of the persisted type information.
+ * @return either the existing map, or a loaded map from the persistent type info cache, or a new empty map if
+ * neither an existing map or a persistent cached type info is available.
+ */
+ @SuppressWarnings("unused")
+ private static Map<Integer, Type> getEffectiveInvalidatedProgramPoints(
+ final Map<Integer, Type> invalidatedProgramPoints, final Object typeInformationFile) {
+ if(invalidatedProgramPoints != null) {
+ return invalidatedProgramPoints;
}
+ final Map<Integer, Type> loadedProgramPoints = OptimisticTypesPersistence.load(typeInformationFile);
+ return loadedProgramPoints != null ? loadedProgramPoints : new TreeMap<Integer, Type>();
+ }
+
+ private FunctionInitializer compileTypeSpecialization(final MethodType actualCallSiteType, final ScriptObject runtimeScope, final boolean persist) {
+ // We're creating an empty script object for holding local variables. AssignSymbols will populate it with
+ // explicit Undefined values for undefined local variables (see AssignSymbols#defineSymbol() and
+ // CompilationEnvironment#declareLocalSymbol()).
- ensureCompiled();
+ if (log.isEnabled()) {
+ log.info("Parameter type specialization of '", functionName, "' signature: ", actualCallSiteType);
+ }
- /*
- * We can't get to this program point unless we have bytecode, either from
- * eager compilation or from running a lazy compile on the lines above
- */
+ final boolean persistentCache = usePersistentCodeCache() && persist;
+ String cacheKey = null;
+ if (persistentCache) {
+ final TypeMap typeMap = typeMap(actualCallSiteType);
+ final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+ cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
+ final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
+ final StoredScript script = newInstaller.loadScript(source, cacheKey);
- assert functionNode == null || functionNode.hasState(CompilationState.EMITTED) :
- functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
+ if (script != null) {
+ Compiler.updateCompilationId(script.getCompilationId());
+ return installStoredScript(script, newInstaller);
+ }
+ }
- // code exists - look it up and add it into the automatically sorted invoker list
- addCode(functionNode);
+ final FunctionNode fn = reparse();
+ final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
+ final FunctionNode compiledFn = compiler.compile(fn,
+ isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL);
- if (functionNode != null && !functionNode.canSpecialize()) {
- // allow GC to claim IR stuff that is not needed anymore
- functionNode = null;
- installer = null;
+ if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
+ compiler.persistClassInfo(cacheKey, compiledFn);
}
+ return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
}
- private MethodHandle addCode(final FunctionNode fn) {
- return addCode(fn, null, null, null);
- }
+ private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) {
+ final Map<String, Class<?>> installedClasses = new HashMap<>();
+ final Map<String, byte[]> classBytes = script.getClassBytes();
+ final String mainClassName = script.getMainClassName();
+ final byte[] mainClassBytes = classBytes.get(mainClassName);
+
+ final Class<?> mainClass = installer.install(mainClassName, mainClassBytes);
+
+ installedClasses.put(mainClassName, mainClass);
- private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
- assert methodLocator != null;
- MethodHandle target = methodLocator.getMethodHandle();
- final MethodType targetType = methodLocator.getMethodType();
+ for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
+ final String className = entry.getKey();
+ final byte[] bytecode = entry.getValue();
- /*
- * For any integer argument. a double that is representable as an integer is OK.
- * otherwise the guard would have failed. in that case introduce a filter that
- * casts the double to an integer, which we know will preserve all precision.
- */
- for (int i = 0; i < targetType.parameterCount(); i++) {
- if (targetType.parameterType(i) == int.class) {
- //representable as int
- target = MH.filterArguments(target, i, ENSURE_INT);
+ if (className.equals(mainClassName)) {
+ continue;
}
+
+ installedClasses.put(className, installer.install(className, bytecode));
}
+ return installedClasses;
+ }
- MethodHandle mh = target;
- if (guard != null) {
- mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
+ /**
+ * Install this script using the given {@code installer}.
+ *
+ * @param script the compiled script
+ * @return the function initializer
+ */
+ private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) {
+ final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller);
+
+ final Map<Integer, FunctionInitializer> initializers = script.getInitializers();
+ assert initializers != null;
+ assert initializers.size() == 1;
+ final FunctionInitializer initializer = initializers.values().iterator().next();
+
+ final Object[] constants = script.getConstants();
+ for (int i = 0; i < constants.length; i++) {
+ if (constants[i] instanceof RecompilableScriptFunctionData) {
+ // replace deserialized function data with the ones we already have
+ constants[i] = getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
+ }
}
- final CompiledFunction cf = new CompiledFunction(runtimeType == null ? targetType : runtimeType, mh);
- code.add(cf);
+ newInstaller.initialize(installedClasses.values(), source, constants);
+ initializer.setCode(installedClasses.get(initializer.getClassName()));
+ return initializer;
+ }
- return cf.getInvoker();
+ boolean usePersistentCodeCache() {
+ final ScriptEnvironment env = installer.getOwner();
+ return env._persistent_cache && env._optimistic_types;
}
- private static Type runtimeType(final Object arg) {
- if (arg == null) {
- return Type.OBJECT;
+ private MethodType explicitParams(final MethodType callSiteType) {
+ if (CompiledFunction.isVarArgsType(callSiteType)) {
+ return null;
}
- final Class<?> clazz = arg.getClass();
- assert !clazz.isPrimitive() : "always boxed";
- if (clazz == Double.class) {
- return JSType.isRepresentableAsInt((double)arg) ? Type.INT : Type.NUMBER;
- } else if (clazz == Integer.class) {
- return Type.INT;
- } else if (clazz == Long.class) {
- return Type.LONG;
- } else if (clazz == String.class) {
- return Type.STRING;
+ final MethodType noCalleeThisType = callSiteType.dropParameterTypes(0, 2); // (callee, this) is always in call site type
+ final int callSiteParamCount = noCalleeThisType.parameterCount();
+
+ // Widen parameters of reference types to Object as we currently don't care for specialization among reference
+ // types. E.g. call site saying (ScriptFunction, Object, String) should still link to (ScriptFunction, Object, Object)
+ final Class<?>[] paramTypes = noCalleeThisType.parameterArray();
+ boolean changed = false;
+ for (int i = 0; i < paramTypes.length; ++i) {
+ final Class<?> paramType = paramTypes[i];
+ if (!(paramType.isPrimitive() || paramType == Object.class)) {
+ paramTypes[i] = Object.class;
+ changed = true;
+ }
}
- return Type.OBJECT;
- }
+ final MethodType generalized = changed ? MethodType.methodType(noCalleeThisType.returnType(), paramTypes) : noCalleeThisType;
- private static boolean canCoerce(final Object arg, final Type type) {
- Type argType = runtimeType(arg);
- if (Type.widest(argType, type) == type || arg == ScriptRuntime.UNDEFINED) {
- return true;
+ if (callSiteParamCount < getArity()) {
+ return generalized.appendParameterTypes(Collections.<Class<?>>nCopies(getArity() - callSiteParamCount, Object.class));
}
- System.err.println(arg + " does not fit in "+ argType + " " + type + " " + arg.getClass());
- new Throwable().printStackTrace();
- return false;
+ return generalized;
}
- @SuppressWarnings("unused")
- private static boolean paramTypeGuard(final Type[] paramTypes, final Object... args) {
- final int length = args.length;
- assert args.length >= paramTypes.length;
-
- //i==start, skip the this, callee params etc
- int start = args.length - paramTypes.length;
- for (int i = start; i < args.length; i++) {
- final Object arg = args[i];
- if (!canCoerce(arg, paramTypes[i - start])) {
+ private FunctionNode extractFunctionFromScript(final FunctionNode script) {
+ final Set<FunctionNode> fns = new HashSet<>();
+ script.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @Override
+ public boolean enterFunctionNode(final FunctionNode fn) {
+ fns.add(fn);
return false;
}
+ });
+ assert fns.size() == 1 : "got back more than one method in recompilation";
+ final FunctionNode f = fns.iterator().next();
+ assert f.getId() == functionNodeId;
+ if (!getFunctionFlag(FunctionNode.IS_DECLARED) && f.isDeclared()) {
+ return f.clearFlag(null, FunctionNode.IS_DECLARED);
+ }
+ return f;
+ }
+
+ private void logLookup(final boolean shouldLog, final MethodType targetType) {
+ if (shouldLog && log.isEnabled()) {
+ log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
}
- return true;
}
- @SuppressWarnings("unused")
- private static int ensureInt(final Object arg) {
- if (arg instanceof Number) {
- return ((Number)arg).intValue();
- } else if (arg instanceof Undefined) {
- return 0;
+ private MethodHandle lookup(final FunctionInitializer fnInit, final boolean shouldLog) {
+ final MethodType type = fnInit.getMethodType();
+ logLookup(shouldLog, type);
+ return lookupCodeMethod(fnInit.getCode(), type);
+ }
+
+ MethodHandle lookup(final FunctionNode fn) {
+ final MethodType type = new FunctionSignature(fn).getMethodType();
+ logLookup(true, type);
+ return lookupCodeMethod(fn.getCompileUnit().getCode(), type);
+ }
+
+ MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
+ return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
+ }
+
+ /**
+ * Initializes this function data with the eagerly generated version of the code. This method can only be invoked
+ * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it
+ * externally will result in an exception.
+ *
+ * @param initializer FunctionInitializer for this data
+ */
+ public void initializeCode(final FunctionInitializer initializer) {
+ // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit.
+ if(!code.isEmpty()) {
+ throw new IllegalStateException(name);
}
- throw new AssertionError(arg);
+ addCode(lookup(initializer, true), null, null, initializer.getFlags());
+ }
+
+ private CompiledFunction addCode(final MethodHandle target, final Map<Integer, Type> invalidatedProgramPoints,
+ final MethodType callSiteType, final int fnFlags) {
+ final CompiledFunction cfn = new CompiledFunction(target, this, invalidatedProgramPoints, callSiteType, fnFlags);
+ code.add(cfn);
+ return cfn;
}
/**
- * Given the runtime callsite args, compute a method type that is equivalent to what
- * was passed - this is typically a lot more specific that what the compiler has been
- * able to deduce
- * @param callSiteType callsite type for the compiled callsite target
- * @param args runtime arguments to the compiled callsite target
- * @return adjusted method type, narrowed as to conform to runtime callsite type instead
+ * Add code with specific call site type. It will adapt the type of the looked up method handle to fit the call site
+ * type. This is necessary because even if we request a specialization that takes an "int" parameter, we might end
+ * up getting one that takes a "double" etc. because of internal function logic causes widening (e.g. assignment of
+ * a wider value to the parameter variable). However, we use the method handle type for matching subsequent lookups
+ * for the same specialization, so we must adapt the handle to the expected type.
+ * @param fnInit the function
+ * @param callSiteType the call site type
+ * @return the compiled function object, with its type matching that of the call site type.
*/
- private static MethodType runtimeType(final MethodType callSiteType, final Object[] args) {
- if (args == null) {
- //for example bound, or otherwise runtime arguments to callsite unavailable, then
- //do not change the type
- return callSiteType;
+ private CompiledFunction addCode(final FunctionInitializer fnInit, final MethodType callSiteType) {
+ if (isVariableArity()) {
+ return addCode(lookup(fnInit, true), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
+ }
+
+ final MethodHandle handle = lookup(fnInit, true);
+ final MethodType fromType = handle.type();
+ MethodType toType = needsCallee(fromType) ? callSiteType.changeParameterType(0, ScriptFunction.class) : callSiteType.dropParameterTypes(0, 1);
+ toType = toType.changeReturnType(fromType.returnType());
+
+ final int toCount = toType.parameterCount();
+ final int fromCount = fromType.parameterCount();
+ final int minCount = Math.min(fromCount, toCount);
+ for(int i = 0; i < minCount; ++i) {
+ final Class<?> fromParam = fromType.parameterType(i);
+ final Class<?> toParam = toType.parameterType(i);
+ // If method has an Object parameter, but call site had String, preserve it as Object. No need to narrow it
+ // artificially. Note that this is related to how CompiledFunction.matchesCallSite() works, specifically
+ // the fact that various reference types compare to equal (see "fnType.isEquivalentTo(csType)" there).
+ if (fromParam != toParam && !fromParam.isPrimitive() && !toParam.isPrimitive()) {
+ assert fromParam.isAssignableFrom(toParam);
+ toType = toType.changeParameterType(i, fromParam);
+ }
}
- final Class<?>[] paramTypes = new Class<?>[callSiteType.parameterCount()];
- final int start = args.length - callSiteType.parameterCount();
- for (int i = start; i < args.length; i++) {
- paramTypes[i - start] = runtimeType(args[i]).getTypeClass();
+ if (fromCount > toCount) {
+ toType = toType.appendParameterTypes(fromType.parameterList().subList(toCount, fromCount));
+ } else if (fromCount < toCount) {
+ toType = toType.dropParameterTypes(fromCount, toCount);
}
- return MH.type(callSiteType.returnType(), paramTypes);
+
+ return addCode(lookup(fnInit, false).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
}
- private static ArrayList<Type> runtimeType(final MethodType mt) {
- final ArrayList<Type> type = new ArrayList<>();
- for (int i = 0; i < mt.parameterCount(); i++) {
- type.add(Type.typeFor(mt.parameterType(i)));
- }
- return type;
+ /**
+ * Returns the return type of a function specialization for particular parameter types.<br>
+ * <b>Be aware that the way this is implemented, it forces full materialization (compilation and installation) of
+ * code for that specialization.</b>
+ * @param callSiteType the parameter types at the call site. It must include the mandatory {@code callee} and
+ * {@code this} parameters, so it needs to start with at least {@code ScriptFunction.class} and
+ * {@code Object.class} class. Since the return type of the function is calculated from the code itself, it is
+ * irrelevant and should be set to {@code Object.class}.
+ * @param runtimeScope a current runtime scope. Can be null but when it's present it will be used as a source of
+ * current runtime values that can improve the compiler's type speculations (and thus reduce the need for later
+ * recompilations) if the specialization is not already present and thus needs to be freshly compiled.
+ * @return the return type of the function specialization.
+ */
+ public Class<?> getReturnType(final MethodType callSiteType, final ScriptObject runtimeScope) {
+ return getBest(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS).type().returnType();
}
@Override
- synchronized MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
- final MethodType runtimeType = runtimeType(callSiteType, args);
- assert runtimeType.parameterCount() == callSiteType.parameterCount();
-
- final MethodHandle mh = super.getBestInvoker(runtimeType, args);
-
- /*
- * Not all functions can be specialized, for example, if we deemed memory
- * footprint too large to store a parse snapshot, or if it is meaningless
- * to do so, such as e.g. for runScript
- */
- if (functionNode == null || !functionNode.canSpecialize()) {
- return mh;
- }
-
- /*
- * Check if best invoker is equally specific or more specific than runtime
- * type. In that case, we don't need further specialization, but can use
- * whatever we have already. We know that it will match callSiteType, or it
- * would not have been returned from getBestInvoker
- */
- if (!code.isLessSpecificThan(runtimeType)) {
- return mh;
- }
-
- int i;
- final FunctionNode snapshot = functionNode.getSnapshot();
- assert snapshot != null;
-
- /*
- * Create a list of the arg types that the compiler knows about
- * typically, the runtime args are a lot more specific, and we should aggressively
- * try to use those whenever possible
- * We WILL try to make an aggressive guess as possible, and add guards if needed.
- * For example, if the compiler can deduce that we have a number type, but the runtime
- * passes and int, we might still want to keep it an int, and the gamble to
- * check that whatever is passed is int representable usually pays off
- * If the compiler only knows that a parameter is an "Object", it is still worth
- * it to try to specialize it by looking at the runtime arg.
- */
- final LinkedList<Type> compileTimeArgs = new LinkedList<>();
- for (i = callSiteType.parameterCount() - 1; i >= 0 && compileTimeArgs.size() < snapshot.getParameters().size(); i--) {
- compileTimeArgs.addFirst(Type.typeFor(callSiteType.parameterType(i)));
- }
-
- /*
- * The classes known at compile time are a safe to generate as primitives without parameter guards
- * But the classes known at runtime (if more specific than compile time types) are safe to generate as primitives
- * IFF there are parameter guards
- */
- MethodHandle guard = null;
- final ArrayList<Type> runtimeParamTypes = runtimeType(runtimeType);
- while (runtimeParamTypes.size() > functionNode.getParameters().size()) {
- runtimeParamTypes.remove(0);
- }
- for (i = 0; i < compileTimeArgs.size(); i++) {
- final Type rparam = Type.typeFor(runtimeType.parameterType(i));
- final Type cparam = compileTimeArgs.get(i);
-
- if (cparam.isObject() && !rparam.isObject()) {
- //check that the runtime object is still coercible to the runtime type, because compiler can't prove it's always primitive
- if (guard == null) {
- guard = MH.insertArguments(PARAM_TYPE_GUARD, 0, (Object)runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]));
- }
+ synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden);
+ if (existingBest == null) {
+ existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType);
+ }
+
+ assert existingBest != null;
+ //we are calling a vararg method with real args
+ boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
+
+ //if the best one is an apply to call, it has to match the callsite exactly
+ //or we need to regenerate
+ if (existingBest.isApplyToCall()) {
+ final CompiledFunction best = lookupExactApplyToCall(callSiteType);
+ if (best != null) {
+ return best;
}
+ varArgWithRealArgs = true;
}
- Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
-
- assert snapshot != functionNode;
+ if (varArgWithRealArgs) {
+ // special case: we had an apply to call, but we failed to make it fit.
+ // Try to generate a specialized one for this callsite. It may
+ // be another apply to call specialization, or it may not, but whatever
+ // it is, it is a specialization that is guaranteed to fit
+ final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
+ existingBest = addCode(fnInit, callSiteType);
+ }
- final Compiler compiler = new Compiler(installer);
+ return existingBest;
+ }
- final FunctionNode compiledSnapshot = compiler.compile(
- snapshot.setHints(
- null,
- new Compiler.Hints(runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]))));
+ @Override
+ boolean isRecompilable() {
+ return true;
+ }
- /*
- * No matter how narrow your types were, they can never be narrower than Attr during recompile made them. I.e. you
- * can put an int into the function here, if you see it as a runtime type, but if the function uses a multiplication
- * on it, it will still need to be a double. At least until we have overflow checks. Similarly, if an int is
- * passed but it is used as a string, it makes no sense to make the parameter narrower than Object. At least until
- * the "different types for one symbol in difference places" work is done
- */
- compiler.install(compiledSnapshot);
+ @Override
+ public boolean needsCallee() {
+ return getFunctionFlag(FunctionNode.NEEDS_CALLEE);
+ }
- return addCode(compiledSnapshot, runtimeType, guard, mh);
+ /**
+ * Returns the {@link FunctionNode} flags associated with this function data.
+ * @return the {@link FunctionNode} flags associated with this function data.
+ */
+ public int getFunctionFlags() {
+ return functionFlags;
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(MethodHandles.lookup(), RecompilableScriptFunctionData.class, name, MH.type(rtype, types));
+ @Override
+ MethodType getGenericType() {
+ // 2 is for (callee, this)
+ if (isVariableArity()) {
+ return MethodType.genericMethodType(2, true);
+ }
+ return MethodType.genericMethodType(2 + getArity());
}
/**
- * Helper class that allows us to retrieve the method handle for this function once it has been generated.
+ * Return the function node id.
+ * @return the function node id
*/
- private static class MethodLocator implements Serializable {
- private transient Class<?> clazz;
- private final String className;
- private final String methodName;
- private final MethodType methodType;
-
- private static final long serialVersionUID = -5420835725902966692L;
+ public int getFunctionNodeId() {
+ return functionNodeId;
+ }
- MethodLocator(final FunctionNode functionNode) {
- this.className = functionNode.getCompileUnit().getUnitClassName();
- this.methodName = functionNode.getName();
- this.methodType = new FunctionSignature(functionNode).getMethodType();
+ /**
+ * Get the source for the script
+ * @return source
+ */
+ public Source getSource() {
+ return source;
+ }
- assert className != null;
- assert methodName != null;
+ /**
+ * Return a script function data based on a function id, either this function if
+ * the id matches or a nested function based on functionId. This goes down into
+ * nested functions until all leaves are exhausted.
+ *
+ * @param functionId function id
+ * @return script function data or null if invalid id
+ */
+ public RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
+ if (functionId == functionNodeId) {
+ return this;
}
+ RecompilableScriptFunctionData data;
- void setClass(final Class<?> clazz) {
- if (!JS.class.isAssignableFrom(clazz)) {
- throw new IllegalArgumentException();
+ data = nestedFunctions == null ? null : nestedFunctions.get(functionId);
+ if (data != null) {
+ return data;
+ }
+ for (final RecompilableScriptFunctionData ndata : nestedFunctions.values()) {
+ data = ndata.getScriptFunctionData(functionId);
+ if (data != null) {
+ return data;
}
- this.clazz = clazz;
}
+ return null;
+ }
- String getClassName() {
- return className;
- }
+ /**
+ * Check whether a certain name is a global symbol, i.e. only exists as defined
+ * in outermost scope and not shadowed by being parameter or assignment in inner
+ * scopes
+ *
+ * @param functionNode function node to check
+ * @param symbolName symbol name
+ * @return true if global symbol
+ */
+ public boolean isGlobalSymbol(final FunctionNode functionNode, final String symbolName) {
+ RecompilableScriptFunctionData data = getScriptFunctionData(functionNode.getId());
+ assert data != null;
- MethodType getMethodType() {
- return methodType;
- }
+ do {
+ if (data.hasInternalSymbol(symbolName)) {
+ return false;
+ }
+ data = data.getParent();
+ } while(data != null);
- MethodHandle getMethodHandle() {
- return MH.findStatic(LOOKUP, clazz, methodName, methodType);
- }
+ return true;
}
-}
+ /**
+ * Restores the {@link #getFunctionFlags()} flags to a function node. During on-demand compilation, we might need
+ * to restore flags to a function node that was otherwise not subjected to a full compile pipeline (e.g. its parse
+ * was skipped, or it's a nested function of a deserialized function.
+ * @param lc current lexical context
+ * @param fn the function node to restore flags onto
+ * @return the transformed function node
+ */
+ public FunctionNode restoreFlags(final LexicalContext lc, final FunctionNode fn) {
+ assert fn.getId() == functionNodeId;
+ FunctionNode newFn = fn.setFlags(lc, functionFlags);
+ // This compensates for missing markEval() in case the function contains an inner function
+ // that contains eval(), that now we didn't discover since we skipped the inner function.
+ if (newFn.hasNestedEval()) {
+ assert newFn.hasScopeBlock();
+ newFn = newFn.setBody(lc, newFn.getBody().setNeedsScope(null));
+ }
+ return newFn;
+ }
+
+ private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ createLogger();
+ }
+ private void createLogger() {
+ log = initLogger(Context.getContextTrusted());
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/RewriteException.java b/src/jdk/nashorn/internal/runtime/RewriteException.java
new file mode 100644
index 00000000..4c0e0a3a
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/RewriteException.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+
+/**
+ * Used to signal to the linker to relink the callee
+ */
+@SuppressWarnings("serial")
+public final class RewriteException extends Exception {
+ private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+
+ // Runtime scope in effect at the time of the compilation. Used to evaluate types of expressions and prevent overly
+ // optimistic assumptions (which will lead to unnecessary deoptimizing recompilations).
+ private ScriptObject runtimeScope;
+
+ // Contents of bytecode slots
+ private Object[] byteCodeSlots;
+
+ private final int[] previousContinuationEntryPoints;
+
+ /** Call for getting the contents of the bytecode slots in the exception */
+ public static final Call GET_BYTECODE_SLOTS = virtualCallNoLookup(RewriteException.class, "getByteCodeSlots", Object[].class);
+ /** Call for getting the program point in the exception */
+ public static final Call GET_PROGRAM_POINT = virtualCallNoLookup(RewriteException.class, "getProgramPoint", int.class);
+ /** Call for getting the return value for the exception */
+ public static final Call GET_RETURN_VALUE = virtualCallNoLookup(RewriteException.class, "getReturnValueDestructive", Object.class);
+ /** Call for the populate array bootstrap */
+ public static final Call BOOTSTRAP = staticCallNoLookup(RewriteException.class, "populateArrayBootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);
+
+ /** Call for populating an array with local variable state */
+ private static final Call POPULATE_ARRAY = staticCall(MethodHandles.lookup(), RewriteException.class, "populateArray", Object[].class, Object[].class, int.class, Object[].class);
+
+ /** Call for converting an array to a long array. */
+ public static final Call TO_LONG_ARRAY = staticCallNoLookup(RewriteException.class, "toLongArray", long[].class, Object.class, RewriteException.class);
+ /** Call for converting an array to a double array. */
+ public static final Call TO_DOUBLE_ARRAY = staticCallNoLookup(RewriteException.class, "toDoubleArray", double[].class, Object.class, RewriteException.class);
+ /** Call for converting an array to an object array. */
+ public static final Call TO_OBJECT_ARRAY = staticCallNoLookup(RewriteException.class, "toObjectArray", Object[].class, Object.class, RewriteException.class);
+ /** Call for converting an object to null if it can't be represented as an instance of a class. */
+ public static final Call INSTANCE_OR_NULL = staticCallNoLookup(RewriteException.class, "instanceOrNull", Object.class, Object.class, Class.class);
+ /** Call for asserting the length of an array. */
+ public static final Call ASSERT_ARRAY_LENGTH = staticCallNoLookup(RewriteException.class, "assertArrayLength", void.class, Object[].class, int.class);
+
+ private RewriteException(
+ final UnwarrantedOptimismException e,
+ final Object[] byteCodeSlots,
+ final String[] byteCodeSymbolNames,
+ final int[] previousContinuationEntryPoints) {
+ super("", e, false, Context.DEBUG);
+ this.byteCodeSlots = byteCodeSlots;
+ this.runtimeScope = mergeSlotsWithScope(byteCodeSlots, byteCodeSymbolNames);
+ this.previousContinuationEntryPoints = previousContinuationEntryPoints;
+ }
+
+ /**
+ * Constructor for a rewrite exception thrown from an optimistic function.
+ * @param e the {@link UnwarrantedOptimismException} that triggered this exception.
+ * @param byteCodeSlots contents of local variable slots at the time of rewrite at the program point
+ * @param byteCodeSymbolNames the names of the variables in the {@code byteCodeSlots} parameter. The array might
+ * have less elements, and some elements might be unnamed (the name can be null). The information is provided in an
+ * effort to assist evaluation of expressions for their types by the compiler doing the deoptimizing recompilation,
+ * and can thus be incomplete - the more complete it is, the more expressions can be evaluated by the compiler, and
+ * the more unnecessary deoptimizing compilations can be avoided.
+ * @return a new rewrite exception
+ */
+ public static RewriteException create(final UnwarrantedOptimismException e,
+ final Object[] byteCodeSlots,
+ final String[] byteCodeSymbolNames) {
+ return create(e, byteCodeSlots, byteCodeSymbolNames, null);
+ }
+
+ /**
+ * Constructor for a rewrite exception thrown from a rest-of method.
+ * @param e the {@link UnwarrantedOptimismException} that triggered this exception.
+ * @param byteCodeSlots contents of local variable slots at the time of rewrite at the program point
+ * @param byteCodeSymbolNames the names of the variables in the {@code byteCodeSlots} parameter. The array might
+ * have less elements, and some elements might be unnamed (the name can be null). The information is provided in an
+ * effort to assist evaluation of expressions for their types by the compiler doing the deoptimizing recompilation,
+ * and can thus be incomplete - the more complete it is, the more expressions can be evaluated by the compiler, and
+ * the more unnecessary deoptimizing compilations can be avoided.
+ * @param previousContinuationEntryPoints an array of continuation entry points that were already executed during
+ * one logical invocation of the function (a rest-of triggering a rest-of triggering a...)
+ * @return a new rewrite exception
+ */
+ public static RewriteException create(final UnwarrantedOptimismException e,
+ final Object[] byteCodeSlots,
+ final String[] byteCodeSymbolNames,
+ final int[] previousContinuationEntryPoints) {
+ return new RewriteException(e, byteCodeSlots, byteCodeSymbolNames, previousContinuationEntryPoints);
+ }
+
+ /**
+ * Bootstrap method for populate array
+ * @param lookup lookup
+ * @param name name (ignored)
+ * @param type method type for signature
+ * @param startIndex start index to start writing to
+ * @return callsite to array populator (constant)
+ */
+ public static CallSite populateArrayBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int startIndex) {
+ MethodHandle mh = POPULATE_ARRAY.methodHandle();
+ mh = MH.insertArguments(mh, 1, startIndex);
+ mh = MH.asCollector(mh, Object[].class, type.parameterCount() - 1);
+ mh = MH.asType(mh, type);
+ return new ConstantCallSite(mh);
+ }
+
+ private static ScriptObject mergeSlotsWithScope(final Object[] byteCodeSlots, final String[] byteCodeSymbolNames) {
+ final ScriptObject locals = Global.newEmptyInstance();
+ final int l = Math.min(byteCodeSlots.length, byteCodeSymbolNames.length);
+ ScriptObject runtimeScope = null;
+ final String scopeName = CompilerConstants.SCOPE.symbolName();
+ for(int i = 0; i < l; ++i) {
+ final String name = byteCodeSymbolNames[i];
+ final Object value = byteCodeSlots[i];
+ if(scopeName.equals(name)) {
+ assert runtimeScope == null;
+ runtimeScope = (ScriptObject)value;
+ } else if(name != null) {
+ locals.set(name, value, NashornCallSiteDescriptor.CALLSITE_STRICT);
+ }
+ }
+ locals.setProto(runtimeScope);
+ return locals;
+ }
+
+ /**
+ * Array populator used for saving the local variable state into the array contained in the
+ * RewriteException
+ * @param arrayToBePopluated array to be populated
+ * @param startIndex start index to write to
+ * @param items items with which to populate the array
+ * @return the populated array - same array object
+ */
+ public static Object[] populateArray(final Object[] arrayToBePopluated, final int startIndex, final Object[] items) {
+ System.arraycopy(items, 0, arrayToBePopluated, startIndex, items.length);
+ return arrayToBePopluated;
+ }
+
+ /**
+ * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+ * a long array in the continued method. Normally, it will also be a long array in the original (interrupted by
+ * deoptimization) method, but it can actually be an int array that underwent widening in the new code version.
+ * @param obj the object that has to be converted into a long array
+ * @param e the exception being processed
+ * @return a long array
+ */
+ public static long[] toLongArray(final Object obj, final RewriteException e) {
+ if(obj instanceof long[]) {
+ return (long[])obj;
+ }
+
+ assert obj instanceof int[];
+
+ final int[] in = (int[])obj;
+ final long[] out = new long[in.length];
+ for(int i = 0; i < in.length; ++i) {
+ out[i] = in[i];
+ }
+ return e.replaceByteCodeValue(in, out);
+ }
+
+ /**
+ * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+ * a double array in the continued method. Normally, it will also be a double array in the original (interrupted by
+ * deoptimization) method, but it can actually be an int or long array that underwent widening in the new code version.
+ * @param obj the object that has to be converted into a double array
+ * @param e the exception being processed
+ * @return a double array
+ */
+ public static double[] toDoubleArray(final Object obj, final RewriteException e) {
+ if(obj instanceof double[]) {
+ return (double[])obj;
+ }
+
+ assert obj instanceof int[] || obj instanceof long[];
+
+ final int l = Array.getLength(obj);
+ final double[] out = new double[l];
+ for(int i = 0; i < l; ++i) {
+ out[i] = Array.getDouble(obj, i);
+ }
+ return e.replaceByteCodeValue(obj, out);
+ }
+
+ /**
+ * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+ * an Object array in the continued method. Normally, it will also be an Object array in the original (interrupted by
+ * deoptimization) method, but it can actually be an int, long, or double array that underwent widening in the new
+ * code version.
+ * @param obj the object that has to be converted into an Object array
+ * @param e the exception being processed
+ * @return an Object array
+ */
+ public static Object[] toObjectArray(final Object obj, final RewriteException e) {
+ if(obj instanceof Object[]) {
+ return (Object[])obj;
+ }
+
+ assert obj instanceof int[] || obj instanceof long[] || obj instanceof double[] : obj + " is " + obj.getClass().getName();
+
+ final int l = Array.getLength(obj);
+ final Object[] out = new Object[l];
+ for(int i = 0; i < l; ++i) {
+ out[i] = Array.get(obj, i);
+ }
+ return e.replaceByteCodeValue(obj, out);
+ }
+
+ /**
+ * Continuation handler calls this method when a local variable carried over into the continuation is expected to
+ * have a certain type, but the value can have a different type coming from the deoptimized method as it was a dead
+ * store. If we had precise liveness analysis, we wouldn't need this.
+ * @param obj the object inspected for being of a particular type
+ * @param clazz the type the object must belong to
+ * @return the object if it belongs to the type, or null otherwise
+ */
+ public static Object instanceOrNull(final Object obj, final Class<?> clazz) {
+ return clazz.isInstance(obj) ? obj : null;
+ }
+
+ /**
+ * Asserts the length of an array. Invoked from continuation handler only when running with assertions enabled.
+ * The array can, in fact, have more elements than asserted, but they must all have Undefined as their value. The
+ * method does not test for the array having less elements than asserted, as those would already have caused an
+ * {@code ArrayIndexOutOfBoundsException} to be thrown as the continuation handler attempts to access the missing
+ * elements.
+ * @param arr the array
+ * @param length the asserted length
+ */
+ public static void assertArrayLength(final Object[] arr, final int length) {
+ for(int i = arr.length; i-- > length;) {
+ if(arr[i] != ScriptRuntime.UNDEFINED) {
+ throw new AssertionError(String.format("Expected array length %d, but it is %d", length, i + 1));
+ }
+ }
+ }
+
+ private <T> T replaceByteCodeValue(final Object in, final T out) {
+ for(int i = 0; i < byteCodeSlots.length; ++i) {
+ if(byteCodeSlots[i] == in) {
+ byteCodeSlots[i] = out;
+ }
+ }
+ return out;
+ }
+
+ private UnwarrantedOptimismException getUOE() {
+ return (UnwarrantedOptimismException)getCause();
+ }
+ /**
+ * Get return value. This method is destructive, after it is invoked subsequent invocation of either
+ * {@link #getByteCodeSlots()} or this method will return null. This method is invoked from the generated
+ * continuation code as the last step before continuing the execution, and we need to make sure we don't hang on to
+ * either the entry bytecode slot values or the return value and prevent them from being garbage collected.
+ * @return return value
+ */
+ public Object getReturnValueDestructive() {
+ assert byteCodeSlots != null;
+ byteCodeSlots = null;
+ runtimeScope = null;
+ return getUOE().getReturnValueDestructive();
+ }
+
+ Object getReturnValueNonDestructive() {
+ return getUOE().getReturnValueNonDestructive();
+ }
+
+ /**
+ * Get return type
+ * @return return type
+ */
+ public Type getReturnType() {
+ return getUOE().getReturnType();
+ }
+
+ /**
+ * Get the program point.
+ * @return program point.
+ */
+ public int getProgramPoint() {
+ return getUOE().getProgramPoint();
+ }
+
+ /**
+ * Get the bytecode slot contents.
+ * @return bytecode slot contents.
+ */
+ public Object[] getByteCodeSlots() {
+ return byteCodeSlots == null ? null : byteCodeSlots.clone();
+ }
+
+ /**
+ * @return an array of continuation entry points that were already executed during one logical invocation of the
+ * function (a rest-of triggering a rest-of triggering a...)
+ */
+ public int[] getPreviousContinuationEntryPoints() {
+ return previousContinuationEntryPoints == null ? null : previousContinuationEntryPoints.clone();
+ }
+
+ /**
+ * Returns the runtime scope that was in effect when the exception was thrown.
+ * @return the runtime scope.
+ */
+ public ScriptObject getRuntimeScope() {
+ return runtimeScope;
+ }
+
+ private static String stringify(final Object returnValue) {
+ if (returnValue == null) {
+ return "null";
+ }
+ String str = returnValue.toString();
+ if (returnValue instanceof String) {
+ str = '\'' + str + '\'';
+ } else if (returnValue instanceof Double) {
+ str = str + 'd';
+ } else if (returnValue instanceof Long) {
+ str = str + 'l';
+ }
+ return str;
+ }
+
+ @Override
+ public String getMessage() {
+ return getMessage(false);
+ }
+
+ /**
+ * Short toString function for message
+ * @return short message
+ */
+ public String getMessageShort() {
+ return getMessage(true);
+ }
+
+ private String getMessage(final boolean isShort) {
+ final StringBuilder sb = new StringBuilder();
+
+ //program point
+ sb.append("[pp=").
+ append(getProgramPoint()).
+ append(", ");
+
+ //slot contents
+ if (!isShort) {
+ final Object[] slots = byteCodeSlots;
+ if (slots != null) {
+ sb.append("slots=").
+ append(Arrays.asList(slots)).
+ append(", ");
+ }
+ }
+
+ //return type
+ sb.append("type=").
+ append(getReturnType()).
+ append(", ");
+
+ //return value
+ sb.append("value=").
+ append(stringify(getReturnValueNonDestructive())).
+ append(")]");
+
+ return sb.toString();
+ }
+
+ private void writeObject(final ObjectOutputStream out) throws NotSerializableException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ private void readObject(final ObjectInputStream in) throws NotSerializableException {
+ throw new NotSerializableException(getClass().getName());
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 445106d7..c7fd0190 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -26,16 +26,18 @@
package jdk.nashorn.internal.runtime;
import java.io.PrintWriter;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
+import java.util.Map;
import java.util.StringTokenizer;
import java.util.TimeZone;
-
+import java.util.logging.Level;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.options.KeyValueOption;
+import jdk.nashorn.internal.runtime.options.LoggingOption;
+import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
import jdk.nashorn.internal.runtime.options.Option;
import jdk.nashorn.internal.runtime.options.Options;
@@ -92,8 +94,14 @@ public final class ScriptEnvironment {
/** Use single Global instance per jsr223 engine instance. */
public final boolean _global_per_engine;
+ /** Enable experimental ECMAScript 6 features. */
+ public final boolean _es6;
+
+ /** Argument passed to compile only if optimistic compilation should take place */
+ public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic";
+
/**
- * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
+ * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
* (function declarations are source elements, but not statements).
*/
public enum FunctionStatementBehavior {
@@ -122,6 +130,9 @@ public final class ScriptEnvironment {
/** Should lazy compilation take place */
public final boolean _lazy_compilation;
+ /** Should optimistic types be used */
+ public final boolean _optimistic_types;
+
/** Create a new class loaded for each compilation */
public final boolean _loader_per_compile;
@@ -149,6 +160,12 @@ public final class ScriptEnvironment {
/** Print resulting bytecode for script */
public final boolean _print_code;
+ /** Directory (optional) to print files to */
+ public final String _print_code_dir;
+
+ /** List of functions to write to the print code dir, optional */
+ public final String _print_code_func;
+
/** Print memory usage for IR after each phase */
public final boolean _print_mem_usage;
@@ -164,15 +181,9 @@ public final class ScriptEnvironment {
/** print symbols and their contents for the script */
public final boolean _print_symbols;
- /** range analysis for known types */
- public final boolean _range_analysis;
-
/** is this environment in scripting mode? */
public final boolean _scripting;
- /** is the JIT allowed to specializ calls based on callsite types? */
- public final Set<String> _specialize_calls;
-
/** is this environment in strict mode? */
public final boolean _strict;
@@ -188,6 +199,12 @@ public final class ScriptEnvironment {
/** Local for error messages */
public final Locale _locale;
+ /** Logging */
+ public final Map<String, LoggerInfo> _loggers;
+
+ /** Timing */
+ public final Timing _timing;
+
/**
* Constructor
*
@@ -195,6 +212,7 @@ public final class ScriptEnvironment {
* @param out output print writer
* @param err error print writer
*/
+ @SuppressWarnings("unused")
public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
this.out = out;
this.err = err;
@@ -210,9 +228,9 @@ public final class ScriptEnvironment {
_early_lvalue_error = options.getBoolean("early.lvalue.error");
_empty_statements = options.getBoolean("empty.statements");
_fullversion = options.getBoolean("fullversion");
- if(options.getBoolean("function.statement.error")) {
+ if (options.getBoolean("function.statement.error")) {
_function_statement = FunctionStatementBehavior.ERROR;
- } else if(options.getBoolean("function.statement.warning")) {
+ } else if (options.getBoolean("function.statement.warning")) {
_function_statement = FunctionStatementBehavior.WARNING;
} else {
_function_statement = FunctionStatementBehavior.ACCEPT;
@@ -220,6 +238,7 @@ public final class ScriptEnvironment {
_fx = options.getBoolean("fx");
_global_per_engine = options.getBoolean("global.per.engine");
_lazy_compilation = options.getBoolean("lazy.compilation");
+ _optimistic_types = options.getBoolean("optimistic.types");
_loader_per_compile = options.getBoolean("loader.per.compile");
_no_java = options.getBoolean("no.java");
_no_syntax_extensions = options.getBoolean("no.syntax.extensions");
@@ -228,28 +247,45 @@ public final class ScriptEnvironment {
_persistent_cache = options.getBoolean("persistent.code.cache");
_print_ast = options.getBoolean("print.ast");
_print_lower_ast = options.getBoolean("print.lower.ast");
- _print_code = options.getBoolean("print.code");
+ _print_code = options.getString("print.code") != null;
_print_mem_usage = options.getBoolean("print.mem.usage");
_print_no_newline = options.getBoolean("print.no.newline");
_print_parse = options.getBoolean("print.parse");
_print_lower_parse = options.getBoolean("print.lower.parse");
_print_symbols = options.getBoolean("print.symbols");
- _range_analysis = options.getBoolean("range.analysis");
_scripting = options.getBoolean("scripting");
_strict = options.getBoolean("strict");
_version = options.getBoolean("version");
_verify_code = options.getBoolean("verify.code");
- final String specialize = options.getString("specialize.calls");
- if (specialize == null) {
- _specialize_calls = null;
+ final String language = options.getString("language");
+ if (language == null || language.equals("es5")) {
+ _es6 = false;
+ } else if (language.equals("es6")) {
+ _es6 = true;
} else {
- _specialize_calls = new HashSet<>();
- final StringTokenizer st = new StringTokenizer(specialize, ",");
- while (st.hasMoreElements()) {
- _specialize_calls.add(st.nextToken());
+ throw new RuntimeException("Unsupported language: " + language);
+ }
+
+ String dir = null;
+ String func = null;
+ final String pc = options.getString("print.code");
+ if (pc != null) {
+ final StringTokenizer st = new StringTokenizer(pc, ",");
+ while (st.hasMoreTokens()) {
+ final StringTokenizer st2 = new StringTokenizer(st.nextToken(), ":");
+ while (st2.hasMoreTokens()) {
+ final String cmd = st2.nextToken();
+ if ("dir".equals(cmd)) {
+ dir = st2.nextToken();
+ } else if ("function".equals(cmd)) {
+ func = st2.nextToken();
+ }
+ }
}
}
+ _print_code_dir = dir;
+ _print_code_func = func;
int callSiteFlags = 0;
if (options.getBoolean("profile.callsites")) {
@@ -268,9 +304,6 @@ public final class ScriptEnvironment {
if (kv.hasValue("objects")) {
callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
}
- if (kv.hasValue("scope")) {
- callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_SCOPE;
- }
}
this._callsite_flags = callSiteFlags;
@@ -287,18 +320,12 @@ public final class ScriptEnvironment {
} else {
this._locale = Locale.getDefault();
}
- }
- /**
- * Can we specialize a particular method name?
- * @param functionName method name
- * @return true if we are allowed to generate versions of this method
- */
- public boolean canSpecialize(final String functionName) {
- if (_specialize_calls == null) {
- return false;
- }
- return _specialize_calls.isEmpty() || _specialize_calls.contains(functionName);
+ final LoggingOption loggingOption = (LoggingOption)options.get("log");
+ this._loggers = loggingOption == null ? new HashMap<String, LoggerInfo>() : loggingOption.getLoggers();
+
+ final LoggerInfo timeLoggerInfo = _loggers.get(Timing.getLoggerName());
+ this._timing = new Timing(timeLoggerInfo != null && timeLoggerInfo.getLevel() != Level.OFF);
}
/**
@@ -343,4 +370,24 @@ public final class ScriptEnvironment {
public List<String> getArguments() {
return options.getArguments();
}
+
+ /**
+ * Check if there is a logger registered for a particular name: typically
+ * the "name" attribute of a Loggable annotation on a class
+ *
+ * @param name logger name
+ * @return true, if a logger exists for that name, false otherwise
+ */
+ public boolean hasLogger(final String name) {
+ return _loggers.get(name) != null;
+ }
+
+ /**
+ * Check if compilation/runtime timings are enabled
+ * @return true if enabled
+ */
+ public boolean isTimingEnabled() {
+ return _timing != null ? _timing.isEnabled() : false;
+ }
+
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
index 3d8b4ff2..d999c118 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -29,18 +29,30 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.codegen.ApplySpecialization;
+import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.linker.NashornGuards;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
/**
* Runtime representation of a JavaScript function.
@@ -48,35 +60,39 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
public abstract class ScriptFunction extends ScriptObject {
/** Method handle for prototype getter for this ScriptFunction */
- public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class);
+ public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class);
/** Method handle for prototype setter for this ScriptFunction */
- public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class);
+ public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class);
/** Method handle for length getter for this ScriptFunction */
- public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class);
+ public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class);
/** Method handle for name getter for this ScriptFunction */
- public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class);
+ public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class);
/** Method handle used for implementing sync() in mozilla_compat */
- public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
+ public static final MethodHandle INVOKE_SYNC = findOwnMH_S("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
/** Method handle for allocate function for this ScriptFunction */
- static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
+ static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class);
- private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+ private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", Object.class, Object.class);
- private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+ private static final MethodHandle SCRIPTFUNCTION_GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
/** method handle to scope getter for this ScriptFunction */
public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
- private static final MethodHandle IS_FUNCTION_MH = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
+ private static final MethodHandle IS_FUNCTION_MH = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
+
+ private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
- private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
+ private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
- private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class);
+ private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH_S("addZerothElement", Object[].class, Object[].class, Object.class);
+
+ private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class));
/** The parent scope. */
private final ScriptObject scope;
@@ -101,7 +117,7 @@ public abstract class ScriptFunction extends ScriptObject {
final MethodHandle methodHandle,
final PropertyMap map,
final ScriptObject scope,
- final MethodHandle[] specs,
+ final Specialization[] specs,
final int flags) {
this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
@@ -195,6 +211,10 @@ public abstract class ScriptFunction extends ScriptObject {
return data.needsWrappedThis();
}
+ private static boolean needsWrappedThis(final Object fn) {
+ return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false;
+ }
+
/**
* Execute this script function.
* @param self Target object.
@@ -230,12 +250,13 @@ public abstract class ScriptFunction extends ScriptObject {
if (Context.DEBUG) {
allocations++;
}
+
assert !isBoundFunction(); // allocate never invoked on bound functions
final ScriptObject object = data.allocate(allocatorMap);
if (object != null) {
- Object prototype = getPrototype();
+ final Object prototype = getPrototype();
if (prototype instanceof ScriptObject) {
object.setInitialProto((ScriptObject)prototype);
}
@@ -311,26 +332,7 @@ public abstract class ScriptFunction extends ScriptObject {
* @param sync the Object to synchronize on, or undefined
* @return synchronized function
*/
- public abstract ScriptFunction makeSynchronizedFunction(Object sync);
-
- /**
- * Return the most appropriate invoke handle if there are specializations
- * @param type most specific method type to look for invocation with
- * @param args args for trampoline invocation
- * @return invoke method handle
- */
- private MethodHandle getBestInvoker(final MethodType type, final Object[] args) {
- return data.getBestInvoker(type, args);
- }
-
- /**
- * Return the most appropriate invoke handle if there are specializations
- * @param type most specific method type to look for invocation with
- * @return invoke method handle
- */
- public MethodHandle getBestInvoker(final MethodType type) {
- return getBestInvoker(type, null);
- }
+ public abstract ScriptFunction makeSynchronizedFunction(Object sync);
/**
* Return the invoke handle bound to a given ScriptObject self reference.
@@ -340,7 +342,7 @@ public abstract class ScriptFunction extends ScriptObject {
* @return bound invoke handle
*/
public final MethodHandle getBoundInvokeHandle(final Object self) {
- return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker()), self);
+ return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), self);
}
/**
@@ -379,7 +381,7 @@ public abstract class ScriptFunction extends ScriptObject {
* @return self's prototype
*/
public static Object G$prototype(final Object self) {
- return (self instanceof ScriptFunction) ?
+ return self instanceof ScriptFunction ?
((ScriptFunction)self).getPrototype() :
UNDEFINED;
}
@@ -428,9 +430,9 @@ public abstract class ScriptFunction extends ScriptObject {
* @param constructor constructor
* @return prototype, or null if given constructor is not a ScriptFunction
*/
- public static ScriptObject getPrototype(final Object constructor) {
- if (constructor instanceof ScriptFunction) {
- final Object proto = ((ScriptFunction)constructor).getPrototype();
+ public static ScriptObject getPrototype(final ScriptFunction constructor) {
+ if (constructor != null) {
+ final Object proto = constructor.getPrototype();
if (proto instanceof ScriptObject) {
return (ScriptObject)proto;
}
@@ -466,12 +468,15 @@ public abstract class ScriptFunction extends ScriptObject {
}
@Override
- protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+ protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType type = desc.getMethodType();
- return new GuardedInvocation(pairArguments(data.getBestConstructor(type.changeParameterType(0, ScriptFunction.class), null), type), null, getFunctionGuard(this));
+ assert desc.getMethodType().returnType() == Object.class && !NashornCallSiteDescriptor.isOptimistic(desc);
+ final CompiledFunction cf = data.getBestConstructor(type, scope, CompiledFunction.NO_FUNCTIONS);
+ final GuardedInvocation bestCtorInv = cf.createConstructorInvocation();
+ //TODO - ClassCastException
+ return new GuardedInvocation(pairArguments(bestCtorInv.getInvocation(), type), getFunctionGuard(this, cf.getFlags()), bestCtorInv.getSwitchPoints(), null);
}
- @SuppressWarnings("unused")
private static Object wrapFilter(final Object obj) {
if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
return obj;
@@ -487,6 +492,35 @@ public abstract class ScriptFunction extends ScriptObject {
}
/**
+ * Some receivers are primitive, in that case, according to the Spec we create a new
+ * native object per callsite with the wrap filter. We can only apply optimistic builtins
+ * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings),
+ * otherwise we can't create optimistic versions
+ *
+ * @param self receiver
+ * @param linkLogicClass linkLogicClass, or null if no link logic exists
+ * @return link logic instance, or null if one could not be constructed for this receiver
+ */
+ private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) {
+ if (linkLogicClass == null) {
+ return LinkLogic.EMPTY_INSTANCE; //always OK to link this, specialization but without special linking logic
+ }
+
+ if (!Context.getContextTrusted().getEnv()._optimistic_types) {
+ return null; //if optimistic types are off, optimistic builtins are too
+ }
+
+ final Object wrappedSelf = wrapFilter(self);
+ if (wrappedSelf instanceof OptimisticBuiltins) {
+ if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) {
+ return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state
+ }
+ return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass);
+ }
+ return null;
+ }
+
+ /**
* dyn:call call site signature: (callee, thiz, [args...])
* generated method signature: (callee, thiz, [args...])
*
@@ -497,51 +531,114 @@ public abstract class ScriptFunction extends ScriptObject {
* (b) method doesn't have callee parameter (builtin functions)
* (3) for local/scope calls, bind thiz and drop both callee and thiz.
* (4) for normal this-calls, drop callee.
+ *
+ * @return guarded invocation for call
*/
@Override
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType type = desc.getMethodType();
- final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
- if (request.isCallSiteUnstable()) {
- // (callee, this, args...) => (callee, this, args[])
- final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
+ final String name = getName();
+ final boolean isUnstable = request.isCallSiteUnstable();
+ final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
+ final boolean isCall = !scopeCall && data.isBuiltin() && "call".equals(name);
+ final boolean isApply = !scopeCall && data.isBuiltin() && "apply".equals(name);
+
+ final boolean isApplyOrCall = isCall | isApply;
+
+ if (isUnstable && !isApplyOrCall) {
+ //megamorphic - replace call with apply
+ final MethodHandle handle;
+ //ensure that the callsite is vararg so apply can consume it
+ if (type.parameterCount() == 3 && type.parameterType(2) == Object[].class) {
+ // Vararg call site
+ handle = ScriptRuntime.APPLY.methodHandle();
+ } else {
+ // (callee, this, args...) => (callee, this, args[])
+ handle = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
+ }
// If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
// generic "is this a ScriptFunction?" guard.
- return new GuardedInvocation(collector, ScriptFunction.class.isAssignableFrom(desc.getMethodType().parameterType(0))
- ? null : NashornGuards.getScriptFunctionGuard());
+ return new GuardedInvocation(
+ handle,
+ null,
+ (SwitchPoint)null,
+ ClassCastException.class);
}
MethodHandle boundHandle;
MethodHandle guard = null;
+ // Special handling of Function.apply and Function.call. Note we must be invoking
+ if (isApplyOrCall && !isUnstable) {
+ final Object[] args = request.getArguments();
+ if (Bootstrap.isCallable(args[1])) {
+ return createApplyOrCallCall(isApply, desc, request, args);
+ }
+ } //else just fall through and link as ordinary function or unstable apply
+
+ int programPoint = INVALID_PROGRAM_POINT;
+ if (NashornCallSiteDescriptor.isOptimistic(desc)) {
+ programPoint = NashornCallSiteDescriptor.getProgramPoint(desc);
+ }
+
+ CompiledFunction cf = data.getBestInvoker(type, scope, CompiledFunction.NO_FUNCTIONS);
+ final Object self = request.getArguments()[1];
+ final Collection<CompiledFunction> forbidden = new HashSet<>();
+
+ //check for special fast versions of the compiled function
+ final List<SwitchPoint> sps = new ArrayList<>();
+ Class<? extends Throwable> exceptionGuard = null;
+
+ while (cf.isSpecialization()) {
+ final Class<? extends LinkLogic> linkLogicClass = cf.getLinkLogicClass();
+ //if linklogic is null, we can always link with the standard mechanism, it's still a specialization
+ final LinkLogic linkLogic = getLinkLogic(self, linkLogicClass);
+
+ if (linkLogic != null && linkLogic.checkLinkable(self, desc, request)) {
+ final DebugLogger log = Context.getContextTrusted().getLogger(Compiler.class);
+
+ if (log.isEnabled()) {
+ log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc);
+ }
+
+ exceptionGuard = linkLogic.getRelinkException();
+
+ break;
+ }
+
+ //could not link this specialization because link check failed
+ forbidden.add(cf);
+ final CompiledFunction oldCf = cf;
+ cf = data.getBestInvoker(type, scope, forbidden);
+ assert oldCf != cf;
+ }
+
+ final GuardedInvocation bestInvoker = cf.createFunctionInvocation(type.returnType(), programPoint);
+ final MethodHandle callHandle = bestInvoker.getInvocation();
+
if (data.needsCallee()) {
- final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
if (scopeCall && needsWrappedThis()) {
- // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
// (callee, this, args...) => (callee, [this], args...)
- boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);
+ boundHandle = MH.filterArguments(callHandle, 1, SCRIPTFUNCTION_GLOBALFILTER);
} else {
// It's already (callee, this, args...), just what we need
boundHandle = callHandle;
}
+ } else if (data.isBuiltin() && "extend".equals(data.getName())) {
+ // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
+ // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
+ boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, type.parameterType(0), type.parameterType(1));
+ } else if (scopeCall && needsWrappedThis()) {
+ // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
+ // (this, args...) => ([this], args...)
+ boundHandle = MH.filterArguments(callHandle, 0, SCRIPTFUNCTION_GLOBALFILTER);
+ // ([this], args...) => ([callee], [this], args...)
+ boundHandle = MH.dropArguments(boundHandle, 0, type.parameterType(0));
} else {
- final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
- if (data.isBuiltin() && "extend".equals(data.getName())) {
- // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
- // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
- boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
- } else if (scopeCall && needsWrappedThis()) {
- // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (this, args...) => ([this], args...)
- boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
- // ([this], args...) => ([callee], [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
- } else {
- // (this, args...) => ([callee], this, args...)
- boundHandle = MH.dropArguments(callHandle, 0, Object.class);
- }
+ // (this, args...) => ([callee], this, args...)
+ boundHandle = MH.dropArguments(callHandle, 0, type.parameterType(0));
}
// For non-strict functions, check whether this-object is primitive type.
@@ -557,8 +654,257 @@ public abstract class ScriptFunction extends ScriptObject {
boundHandle = pairArguments(boundHandle, type);
- return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard);
- }
+ if (bestInvoker.getSwitchPoints() != null) {
+ sps.addAll(Arrays.asList(bestInvoker.getSwitchPoints()));
+ }
+ final SwitchPoint[] spsArray = sps.isEmpty() ? null : sps.toArray(new SwitchPoint[sps.size()]);
+
+ return new GuardedInvocation(
+ boundHandle,
+ guard == null ?
+ getFunctionGuard(
+ this,
+ cf.getFlags()) :
+ guard,
+ spsArray,
+ exceptionGuard);
+ }
+
+ private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) {
+ final MethodType descType = desc.getMethodType();
+ final int paramCount = descType.parameterCount();
+ if(descType.parameterType(paramCount - 1).isArray()) {
+ // This is vararg invocation of apply or call. This can normally only happen when we do a recursive
+ // invocation of createApplyOrCallCall (because we're doing apply-of-apply). In this case, create delegate
+ // linkage by unpacking the vararg invocation and use pairArguments to introduce the necessary spreader.
+ return createVarArgApplyOrCallCall(isApply, desc, request, args);
+ }
+
+ final boolean passesThis = paramCount > 2;
+ final boolean passesArgs = paramCount > 3;
+ final int realArgCount = passesArgs ? paramCount - 3 : 0;
+
+ final Object appliedFn = args[1];
+ final boolean appliedFnNeedsWrappedThis = needsWrappedThis(appliedFn);
+
+ //box call back to apply
+ CallSiteDescriptor appliedDesc = desc;
+ final SwitchPoint applyToCallSwitchPoint = Global.getBuiltinFunctionApplySwitchPoint();
+ //enough to change the proto switchPoint here
+
+ final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc);
+ final boolean isFailedApplyToCall = isApplyToCall && applyToCallSwitchPoint.hasBeenInvalidated();
+
+ // R(apply|call, ...) => R(...)
+ MethodType appliedType = descType.dropParameterTypes(0, 1);
+ if (!passesThis) {
+ // R() => R(this)
+ appliedType = appliedType.insertParameterTypes(1, Object.class);
+ } else if (appliedFnNeedsWrappedThis) {
+ appliedType = appliedType.changeParameterType(1, Object.class);
+ }
+
+ /*
+ * dropArgs is a synthetic method handle that contains any args that we need to
+ * get rid of that come after the arguments array in the apply case. We adapt
+ * the callsite to ask for 3 args only and then dropArguments on the method handle
+ * to make it fit the extraneous args.
+ */
+ MethodType dropArgs = MH.type(void.class);
+ if (isApply && !isFailedApplyToCall) {
+ final int pc = appliedType.parameterCount();
+ for (int i = 3; i < pc; i++) {
+ dropArgs = dropArgs.appendParameterTypes(appliedType.parameterType(i));
+ }
+ if (pc > 3) {
+ appliedType = appliedType.dropParameterTypes(3, pc);
+ }
+ }
+
+ if (isApply || isFailedApplyToCall) {
+ if (passesArgs) {
+ // R(this, args) => R(this, Object[])
+ appliedType = appliedType.changeParameterType(2, Object[].class);
+ // drop any extraneous arguments for the apply fail case
+ if (isFailedApplyToCall) {
+ appliedType = appliedType.dropParameterTypes(3, paramCount - 1);
+ }
+ } else {
+ // R(this) => R(this, Object[])
+ appliedType = appliedType.insertParameterTypes(2, Object[].class);
+ }
+ }
+
+ appliedDesc = appliedDesc.changeMethodType(appliedType); //no extra args
+
+ // Create the same arguments for the delegate linking request that would be passed in an actual apply'd invocation
+ final Object[] appliedArgs = new Object[isApply ? 3 : appliedType.parameterCount()];
+ appliedArgs[0] = appliedFn;
+ appliedArgs[1] = passesThis ? appliedFnNeedsWrappedThis ? ScriptFunctionData.wrapThis(args[2]) : args[2] : ScriptRuntime.UNDEFINED;
+ if (isApply && !isFailedApplyToCall) {
+ appliedArgs[2] = passesArgs ? NativeFunction.toApplyArgs(args[3]) : ScriptRuntime.EMPTY_ARRAY;
+ } else {
+ if (passesArgs) {
+ if (isFailedApplyToCall) {
+ final Object[] tmp = new Object[args.length - 3];
+ System.arraycopy(args, 3, tmp, 0, tmp.length);
+ appliedArgs[2] = NativeFunction.toApplyArgs(tmp);
+ } else {
+ assert !isApply;
+ System.arraycopy(args, 3, appliedArgs, 2, args.length - 3);
+ }
+ } else if (isFailedApplyToCall) {
+ appliedArgs[2] = ScriptRuntime.EMPTY_ARRAY;
+ }
+ }
+
+ // Ask the linker machinery for an invocation of the target function
+ final LinkRequest appliedRequest = request.replaceArguments(appliedDesc, appliedArgs);
+
+ GuardedInvocation appliedInvocation;
+ try {
+ appliedInvocation = Bootstrap.getLinkerServices().getGuardedInvocation(appliedRequest);
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ assert appliedRequest != null; // Bootstrap.isCallable() returned true for args[1], so it must produce a linkage.
+
+ final Class<?> applyFnType = descType.parameterType(0);
+ MethodHandle inv = appliedInvocation.getInvocation(); //method handle from apply invocation. the applied function invocation
+
+ if (isApply && !isFailedApplyToCall) {
+ if (passesArgs) {
+ // Make sure that the passed argArray is converted to Object[] the same way NativeFunction.apply() would do it.
+ inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS);
+ } else {
+ // If the original call site doesn't pass argArray, pass in an empty array
+ inv = MH.insertArguments(inv, 2, (Object)ScriptRuntime.EMPTY_ARRAY);
+ }
+ }
+
+ if (isApplyToCall) {
+ if (isFailedApplyToCall) {
+ //take the real arguments that were passed to a call and force them into the apply instead
+ Context.getContextTrusted().getLogger(ApplySpecialization.class).info("Collection arguments to revert call to apply in " + appliedFn);
+ inv = MH.asCollector(inv, Object[].class, realArgCount);
+ } else {
+ appliedInvocation = appliedInvocation.addSwitchPoint(applyToCallSwitchPoint);
+ }
+ }
+
+ if (!passesThis) {
+ // If the original call site doesn't pass in a thisArg, pass in Global/undefined as needed
+ inv = bindImplicitThis(appliedFn, inv);
+ } else if (appliedFnNeedsWrappedThis) {
+ // target function needs a wrapped this, so make sure we filter for that
+ inv = MH.filterArguments(inv, 1, WRAP_THIS);
+ }
+ inv = MH.dropArguments(inv, 0, applyFnType);
+
+ /*
+ * Dropargs can only be non-()V in the case of isApply && !isFailedApplyToCall, which
+ * is when we need to add arguments to the callsite to catch and ignore the synthetic
+ * extra args that someone has added to the command line.
+ */
+ for (int i = 0; i < dropArgs.parameterCount(); i++) {
+ inv = MH.dropArguments(inv, 4 + i, dropArgs.parameterType(i));
+ }
+
+ MethodHandle guard = appliedInvocation.getGuard();
+ // If the guard checks the value of "this" but we aren't passing thisArg, insert the default one
+ if (!passesThis && guard.type().parameterCount() > 1) {
+ guard = bindImplicitThis(appliedFn, guard);
+ }
+ final MethodType guardType = guard.type();
+
+ // We need to account for the dropped (apply|call) function argument.
+ guard = MH.dropArguments(guard, 0, descType.parameterType(0));
+ // Take the "isApplyFunction" guard, and bind it to this function.
+ MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); //TODO replace this with switchpoint
+ // Adapt the guard to receive all the arguments that the original guard does.
+ applyFnGuard = MH.dropArguments(applyFnGuard, 2, guardType.parameterArray());
+ // Fold the original function guard into our apply guard.
+ guard = MH.foldArguments(applyFnGuard, guard);
+
+ return appliedInvocation.replaceMethods(inv, guard);
+ }
+
+ /*
+ * This method is used for linking nested apply. Specialized apply and call linking will create a variable arity
+ * call site for an apply call; when createApplyOrCallCall sees a linking request for apply or call with
+ * Nashorn-style variable arity call site (last argument type is Object[]) it'll delegate to this method.
+ * This method converts the link request from a vararg to a non-vararg one (unpacks the array), then delegates back
+ * to createApplyOrCallCall (with which it is thus mutually recursive), and adds appropriate argument spreaders to
+ * invocation and the guard of whatever createApplyOrCallCall returned to adapt it back into a variable arity
+ * invocation. It basically reduces the problem of vararg call site linking of apply and call back to the (already
+ * solved by createApplyOrCallCall) non-vararg call site linking.
+ */
+ private GuardedInvocation createVarArgApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc,
+ final LinkRequest request, final Object[] args) {
+ final MethodType descType = desc.getMethodType();
+ final int paramCount = descType.parameterCount();
+ final Object[] varArgs = (Object[])args[paramCount - 1];
+ // -1 'cause we're not passing the vararg array itself
+ final int copiedArgCount = args.length - 1;
+ final int varArgCount = varArgs.length;
+
+ // Spread arguments for the delegate createApplyOrCallCall invocation.
+ final Object[] spreadArgs = new Object[copiedArgCount + varArgCount];
+ System.arraycopy(args, 0, spreadArgs, 0, copiedArgCount);
+ System.arraycopy(varArgs, 0, spreadArgs, copiedArgCount, varArgCount);
+
+ // Spread call site descriptor for the delegate createApplyOrCallCall invocation. We drop vararg array and
+ // replace it with a list of Object.class.
+ final MethodType spreadType = descType.dropParameterTypes(paramCount - 1, paramCount).appendParameterTypes(
+ Collections.<Class<?>>nCopies(varArgCount, Object.class));
+ final CallSiteDescriptor spreadDesc = desc.changeMethodType(spreadType);
+
+ // Delegate back to createApplyOrCallCall with the spread (that is, reverted to non-vararg) request/
+ final LinkRequest spreadRequest = request.replaceArguments(spreadDesc, spreadArgs);
+ final GuardedInvocation spreadInvocation = createApplyOrCallCall(isApply, spreadDesc, spreadRequest, spreadArgs);
+
+ // Add spreader combinators to returned invocation and guard.
+ return spreadInvocation.replaceMethods(
+ // Use standard ScriptObject.pairArguments on the invocation
+ pairArguments(spreadInvocation.getInvocation(), descType),
+ // Use our specialized spreadGuardArguments on the guard (see below).
+ spreadGuardArguments(spreadInvocation.getGuard(), descType));
+ }
+
+ private static MethodHandle spreadGuardArguments(final MethodHandle guard, final MethodType descType) {
+ final MethodType guardType = guard.type();
+ final int guardParamCount = guardType.parameterCount();
+ final int descParamCount = descType.parameterCount();
+ final int spreadCount = guardParamCount - descParamCount + 1;
+ if (spreadCount <= 0) {
+ // Guard doesn't dip into the varargs
+ return guard;
+ }
+
+ final MethodHandle arrayConvertingGuard;
+ // If the last parameter type of the guard is an array, then it is already itself a guard for a vararg apply
+ // invocation. We must filter the last argument with toApplyArgs otherwise deeper levels of nesting will fail
+ // with ClassCastException of NativeArray to Object[].
+ if(guardType.parameterType(guardParamCount - 1).isArray()) {
+ arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS);
+ } else {
+ arrayConvertingGuard = guard;
+ }
+
+ return ScriptObject.adaptHandleToVarArgCallSite(arrayConvertingGuard, descParamCount);
+ }
+
+ private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) {
+ final MethodHandle bound;
+ if(fn instanceof ScriptFunction && ((ScriptFunction)fn).needsWrappedThis()) {
+ bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
+ } else {
+ bound = mh;
+ }
+ return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED);
+ }
/**
* Used for noSuchMethod/noSuchProperty and JSAdapter hooks.
@@ -566,7 +912,7 @@ public abstract class ScriptFunction extends ScriptObject {
* These don't want a callee parameter, so bind that. Name binding is optional.
*/
MethodHandle getCallMethodHandle(final MethodType type, final String bindName) {
- return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type, null)), bindName), type);
+ return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), bindName), type);
}
private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
@@ -594,8 +940,13 @@ public abstract class ScriptFunction extends ScriptObject {
*
* @return method handle for guard
*/
- private static MethodHandle getFunctionGuard(final ScriptFunction function) {
+ private static MethodHandle getFunctionGuard(final ScriptFunction function, final int flags) {
assert function.data != null;
+ // Built-in functions have a 1-1 correspondence to their ScriptFunctionData, so we can use a cheaper identity
+ // comparison for them.
+ if (function.data.isBuiltin()) {
+ return Guards.getIdentityGuard(function);
+ }
return MH.insertArguments(IS_FUNCTION_MH, 1, function.data);
}
@@ -623,10 +974,17 @@ public abstract class ScriptFunction extends ScriptObject {
return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject;
}
+ //TODO this can probably be removed given that we have builtin switchpoints in the context
+ @SuppressWarnings("unused")
+ private static boolean isApplyFunction(final boolean appliedFnCondition, final Object self, final Object expectedSelf) {
+ // NOTE: we're using self == expectedSelf as we're only using this with built-in functions apply() and call()
+ return appliedFnCondition && self == expectedSelf;
+ }
+
@SuppressWarnings("unused")
private static Object[] addZerothElement(final Object[] args, final Object value) {
// extends input array with by adding new zeroth element
- final Object[] src = (args == null)? ScriptRuntime.EMPTY_ARRAY : args;
+ final Object[] src = args == null? ScriptRuntime.EMPTY_ARRAY : args;
final Object[] result = new Object[src.length + 1];
System.arraycopy(src, 0, result, 1, src.length);
result[0] = value;
@@ -642,14 +1000,12 @@ public abstract class ScriptFunction extends ScriptObject {
}
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- final Class<?> own = ScriptFunction.class;
- final MethodType mt = MH.type(rtype, types);
- try {
- return MH.findStatic(MethodHandles.lookup(), own, name, mt);
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), own, name, mt);
- }
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
+ }
+
+ private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
}
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 001996b7..3472cda1 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -28,12 +28,17 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
+import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+
/**
* A container for data needed to instantiate a specific {@link ScriptFunction} at runtime.
@@ -41,19 +46,36 @@ import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
* constants array to reduce function instantiation overhead during runtime.
*/
public abstract class ScriptFunctionData implements Serializable {
+ static final int MAX_ARITY = LinkerCallSite.ARGLIMIT;
+ static {
+ // Assert it fits in a byte, as that's what we store it in. It's just a size optimization though, so if needed
+ // "byte arity" field can be widened.
+ assert MAX_ARITY < 256;
+ }
- /** Name of the function or "" for anonynous functions */
+ /** Name of the function or "" for anonymous functions */
protected final String name;
- /** All versions of this function that have been generated to code */
- protected final CompiledFunctions code;
+ /**
+ * A list of code versions of a function sorted in ascending order of generic descriptors.
+ */
+ protected transient LinkedList<CompiledFunction> code = new LinkedList<>();
/** Function flags */
protected int flags;
+ // Parameter arity of the function, corresponding to "f.length". E.g. "function f(a, b, c) { ... }" arity is 3, and
+ // some built-in ECMAScript functions have their arity declared by the specification. Note that regardless of this
+ // value, the function might still be capable of receiving variable number of arguments, see isVariableArity.
private int arity;
- private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
+ /**
+ * A pair of method handles used for generic invoker and constructor. Field is volatile as it can be initialized by
+ * multiple threads concurrently, but we still tolerate a race condition in it as all values stored into it are
+ * idempotent.
+ */
+ private volatile transient GenericInvokers genericInvokers;
+
private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
/** Is this a strict mode function? */
@@ -66,6 +88,8 @@ public abstract class ScriptFunctionData implements Serializable {
public static final int NEEDS_CALLEE = 1 << 3;
/** Does this function make use of the this-object argument? */
public static final int USES_THIS = 1 << 4;
+ /** Is this a variable arity function? */
+ public static final int IS_VARIABLE_ARITY = 1 << 5;
/** Flag for strict or built-in functions */
public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
@@ -79,39 +103,43 @@ public abstract class ScriptFunctionData implements Serializable {
/**
* Constructor
*
- * @param name script function name
- * @param arity arity
- * @param flags the function flags
+ * @param name script function name
+ * @param arity arity
+ * @param flags the function flags
*/
ScriptFunctionData(final String name, final int arity, final int flags) {
this.name = name;
- this.arity = arity;
- this.code = new CompiledFunctions();
this.flags = flags;
+ setArity(arity);
}
final int getArity() {
return arity;
}
+ final boolean isVariableArity() {
+ return (flags & IS_VARIABLE_ARITY) != 0;
+ }
+
/**
* Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final
* @param arity new arity
*/
void setArity(final int arity) {
+ if(arity < 0 || arity > MAX_ARITY) {
+ throw new IllegalArgumentException(String.valueOf(arity));
+ }
this.arity = arity;
}
CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
- final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args);
+ final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args);
- //TODO the boundinvoker.type() could actually be more specific here
if (isConstructor()) {
- ensureConstructor(originalInv);
- return new CompiledFunction(boundInvoker.type(), boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
+ return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args), null);
}
- return new CompiledFunction(boundInvoker.type(), boundInvoker);
+ return new CompiledFunction(boundInvoker);
}
/**
@@ -122,6 +150,15 @@ public abstract class ScriptFunctionData implements Serializable {
return (flags & IS_STRICT) != 0;
}
+ /**
+ * Return the complete internal function name for this
+ * data, not anonymous or similar. May be identical
+ * @return internal function name
+ */
+ protected String getFunctionName() {
+ return getName();
+ }
+
boolean isBuiltin() {
return (flags & IS_BUILTIN) != 0;
}
@@ -130,11 +167,7 @@ public abstract class ScriptFunctionData implements Serializable {
return (flags & IS_CONSTRUCTOR) != 0;
}
- boolean needsCallee() {
- // we don't know if we need a callee or not unless code has been compiled
- ensureCompiled();
- return (flags & NEEDS_CALLEE) != 0;
- }
+ abstract boolean needsCallee();
/**
* Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
@@ -161,6 +194,14 @@ public abstract class ScriptFunctionData implements Serializable {
*/
@Override
public String toString() {
+ return name.isEmpty() ? "<anonymous>" : name;
+ }
+
+ /**
+ * Verbose description of data
+ * @return verbose description
+ */
+ public String toStringVerbose() {
final StringBuilder sb = new StringBuilder();
sb.append("name='").
@@ -181,44 +222,30 @@ public abstract class ScriptFunctionData implements Serializable {
* and not suddenly a "real" object
*
* @param callSiteType callsite type
- * @param args arguments at callsite on first trampoline invocation
- * @return method handle to best invoker
+ * @return compiled function object representing the best invoker.
*/
- MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
- return getBest(callSiteType).getInvoker();
+ final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) {
+ return getBestInvoker(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS);
}
- MethodHandle getBestInvoker(final MethodType callSiteType) {
- return getBestInvoker(callSiteType, null);
+ final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ final CompiledFunction cf = getBest(callSiteType, runtimeScope, forbidden);
+ assert cf != null;
+ return cf;
}
- MethodHandle getBestConstructor(final MethodType callSiteType, final Object[] args) {
+ final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
if (!isConstructor()) {
throw typeError("not.a.constructor", toSource());
}
- ensureCodeGenerated();
-
- final CompiledFunction best = getBest(callSiteType);
- ensureConstructor(best);
- return best.getConstructor();
- }
-
- MethodHandle getBestConstructor(final MethodType callSiteType) {
- return getBestConstructor(callSiteType, null);
- }
-
- /**
- * Subclass responsibility. If we can have lazy code generation, this is a hook to ensure that
- * code exists before performing an operation.
- */
- protected void ensureCodeGenerated() {
- //empty
+ // Constructor call sites don't have a "this", but getBest is meant to operate on "callee, this, ..." style
+ final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope, forbidden);
+ return cf;
}
/**
* If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
- * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance;
- * use {@link #ensureCodeGenerated()} to install the actual method handles.
+ * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance
*/
protected void ensureCompiled() {
//empty
@@ -229,28 +256,140 @@ public abstract class ScriptFunctionData implements Serializable {
* is generated, get the most generic of all versions of this function and adapt it
* to Objects.
*
- * TODO this is only public because {@link JavaAdapterFactory} can't supply us with
- * a MethodType that we can use for lookup due to boostrapping problems. Can be fixed
- *
+ * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
+ * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
+ * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
* @return generic invoker of this script function
*/
- public final MethodHandle getGenericInvoker() {
- ensureCodeGenerated();
- return code.generic().getInvoker();
+ final MethodHandle getGenericInvoker(final ScriptObject runtimeScope) {
+ // This method has race conditions both on genericsInvoker and genericsInvoker.invoker, but even if invoked
+ // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
+ // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
+ final GenericInvokers lgenericInvokers = ensureGenericInvokers();
+ MethodHandle invoker = lgenericInvokers.invoker;
+ if(invoker == null) {
+ lgenericInvokers.invoker = invoker = createGenericInvoker(runtimeScope);
+ }
+ return invoker;
+ }
+
+ private MethodHandle createGenericInvoker(final ScriptObject runtimeScope) {
+ return makeGenericMethod(getGeneric(runtimeScope).createComposableInvoker());
+ }
+
+ final MethodHandle getGenericConstructor(final ScriptObject runtimeScope) {
+ // This method has race conditions both on genericsInvoker and genericsInvoker.constructor, but even if invoked
+ // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
+ // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
+ final GenericInvokers lgenericInvokers = ensureGenericInvokers();
+ MethodHandle constructor = lgenericInvokers.constructor;
+ if(constructor == null) {
+ lgenericInvokers.constructor = constructor = createGenericConstructor(runtimeScope);
+ }
+ return constructor;
}
- final MethodHandle getGenericConstructor() {
- ensureCodeGenerated();
- ensureConstructor(code.generic());
- return code.generic().getConstructor();
+ private MethodHandle createGenericConstructor(final ScriptObject runtimeScope) {
+ return makeGenericMethod(getGeneric(runtimeScope).createComposableConstructor());
}
- private CompiledFunction getBest(final MethodType callSiteType) {
- ensureCodeGenerated();
- return code.best(callSiteType);
+ private GenericInvokers ensureGenericInvokers() {
+ GenericInvokers lgenericInvokers = genericInvokers;
+ if(lgenericInvokers == null) {
+ genericInvokers = lgenericInvokers = new GenericInvokers();
+ }
+ return lgenericInvokers;
+ }
+
+ private static MethodType widen(final MethodType cftype) {
+ final Class<?>[] paramTypes = new Class<?>[cftype.parameterCount()];
+ for (int i = 0; i < cftype.parameterCount(); i++) {
+ paramTypes[i] = cftype.parameterType(i).isPrimitive() ? cftype.parameterType(i) : Object.class;
+ }
+ return MH.type(cftype.returnType(), paramTypes);
+ }
+
+ /**
+ * Used to find an apply to call version that fits this callsite.
+ * We cannot just, as in the normal matcher case, return e.g. (Object, Object, int)
+ * for (Object, Object, int, int, int) or we will destroy the semantics and get
+ * a function that, when padded with undefineds, behaves differently
+ * @param type actual call site type
+ * @return apply to call that perfectly fits this callsite or null if none found
+ */
+ CompiledFunction lookupExactApplyToCall(final MethodType type) {
+ for (final CompiledFunction cf : code) {
+ if (!cf.isApplyToCall()) {
+ continue;
+ }
+
+ final MethodType cftype = cf.type();
+ if (cftype.parameterCount() != type.parameterCount()) {
+ continue;
+ }
+
+ if (widen(cftype).equals(widen(type))) {
+ return cf;
+ }
+ }
+
+ return null;
+ }
+
+ CompiledFunction pickFunction(final MethodType callSiteType, final boolean canPickVarArg) {
+ for (final CompiledFunction candidate : code) {
+ if (candidate.matchesCallSite(callSiteType, canPickVarArg)) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the best function for the specified call site type.
+ * @param callSiteType The call site type. Call site types are expected to have the form
+ * {@code (callee, this[, args...])}.
+ * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
+ * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
+ * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
+ * @return the best function for the specified call site type.
+ */
+ CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this)
+ assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function
+
+ if (isRecompilable()) {
+ final CompiledFunction candidate = pickFunction(callSiteType, false);
+ if (candidate != null) {
+ return candidate;
+ }
+ return pickFunction(callSiteType, true); //try vararg last
+ }
+
+ CompiledFunction best = null;
+ for (final CompiledFunction candidate: code) {
+ if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
+ best = candidate;
+ }
+ }
+
+ return best;
+ }
+
+
+ abstract boolean isRecompilable();
+
+ CompiledFunction getGeneric(final ScriptObject runtimeScope) {
+ return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS);
}
/**
+ * Get a method type for a generic invoker.
+ * @return the method type for the generic invoker
+ */
+ abstract MethodType getGenericType();
+
+ /**
* Allocates an object using this function's allocator.
*
* @param map the property map for the allocated object.
@@ -278,91 +417,17 @@ public abstract class ScriptFunctionData implements Serializable {
* @param args additional arguments to bind. Can be null.
*/
ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) {
- ensureCodeGenerated();
-
final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
final int length = args == null ? 0 : args.length;
// Clear the callee and this flags
final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
- CompiledFunctions boundList = new CompiledFunctions();
- if (code.size() == 1) {
- // only one variant - bind that
- boundList.add(bind(code.first(), fn, self, allArgs));
- } else {
- // There are specialized versions. Get the most generic one.
- // This is to avoid ambiguous overloaded versions of bound and
- // specialized variants and choosing wrong overload.
- final MethodHandle genInvoker = getGenericInvoker();
- final CompiledFunction inv = new CompiledFunction(genInvoker.type(), genInvoker, getGenericConstructor());
- boundList.add(bind(inv, fn, self, allArgs));
- }
-
- return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags);
- }
-
- /**
- * Compose a constructor given a primordial constructor handle.
- *
- * @param ctor primordial constructor handle
- * @return the composed constructor
- */
- protected MethodHandle composeConstructor(final MethodHandle ctor) {
- // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
- // "this" in the first argument position is what allows the elegant folded composition of
- // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
- // always returns Object.
- final boolean needsCallee = needsCallee(ctor);
- MethodHandle composedCtor = needsCallee ? swapCalleeAndThis(ctor) : ctor;
-
- composedCtor = changeReturnTypeToObject(composedCtor);
-
- final MethodType ctorType = composedCtor.type();
-
- // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
- // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
- // (this, [callee, ]args...) => ([callee, ]args...)
- final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();
-
- // Fold constructor into newFilter that replaces the return value from the constructor with the originally
- // allocated value when the originally allocated value is a primitive.
- // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
- composedCtor = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), composedCtor);
-
- // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
- if (needsCallee) {
- // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
- // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
- // or...
- return MH.foldArguments(composedCtor, ScriptFunction.ALLOCATE);
- }
+ final List<CompiledFunction> boundList = new LinkedList<>();
+ final ScriptObject runtimeScope = fn.getScope();
+ final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope), null);
+ boundList.add(bind(bindTarget, fn, self, allArgs));
- // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
- // (this, args...) filter (callee) => (callee, args...)
- return MH.filterArguments(composedCtor, 0, ScriptFunction.ALLOCATE);
- }
-
- /**
- * If this function's method handles need a callee parameter, swap the order of first two arguments for the passed
- * method handle. If this function's method handles don't need a callee parameter, returns the original method
- * handle unchanged.
- *
- * @param mh a method handle with order of arguments {@code (callee, this, args...)}
- *
- * @return a method handle with order of arguments {@code (this, callee, args...)}
- */
- private static MethodHandle swapCalleeAndThis(final MethodHandle mh) {
- final MethodType type = mh.type();
- assert type.parameterType(0) == ScriptFunction.class : type;
- assert type.parameterType(1) == Object.class : type;
- final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class);
- final int[] reorder = new int[type.parameterCount()];
- reorder[0] = 1;
- assert reorder[1] == 0;
- for (int i = 2; i < reorder.length; ++i) {
- reorder[i] = i;
- }
- return MethodHandles.permuteArguments(mh, newType, reorder);
+ return new FinalScriptFunctionData(name, Math.max(0, getArity() - length), boundList, boundFlags);
}
/**
@@ -373,7 +438,11 @@ public abstract class ScriptFunctionData implements Serializable {
* @return the converted this object
*/
private Object convertThisObject(final Object thiz) {
- if (!(thiz instanceof ScriptObject) && needsWrappedThis()) {
+ return needsWrappedThis() ? wrapThis(thiz) : thiz;
+ }
+
+ static Object wrapThis(final Object thiz) {
+ if (!(thiz instanceof ScriptObject)) {
if (JSType.nullOrUndefined(thiz)) {
return Context.getGlobal();
}
@@ -440,7 +509,7 @@ public abstract class ScriptFunctionData implements Serializable {
} else {
// If target is already bound, insert additional bound arguments after "this" argument, at position 1.
final int argInsertPos = isTargetBound ? 1 : 0;
- final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : (needsCallee ? 2 : 1)))];
+ final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : needsCallee ? 2 : 1))];
int next = 0;
if (!isTargetBound) {
if (needsCallee) {
@@ -506,6 +575,38 @@ public abstract class ScriptFunctionData implements Serializable {
}
/**
+ * Takes a method handle, and returns a potentially different method handle that can be used in
+ * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}.
+ * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into
+ * {@code Object} as well, except for the following ones:
+ * <ul>
+ * <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li>
+ * <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself
+ * (callee) as an argument.</li>
+ * </ul>
+ *
+ * @param mh the original method handle
+ *
+ * @return the new handle, conforming to the rules above.
+ */
+ private static MethodHandle makeGenericMethod(final MethodHandle mh) {
+ final MethodType type = mh.type();
+ final MethodType newType = makeGenericType(type);
+ return type.equals(newType) ? mh : mh.asType(newType);
+ }
+
+ private static MethodType makeGenericType(final MethodType type) {
+ MethodType newType = type.generic();
+ if (isVarArg(type)) {
+ newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class);
+ }
+ if (needsCallee(type)) {
+ newType = newType.changeParameterType(0, ScriptFunction.class);
+ }
+ return newType;
+ }
+
+ /**
* Execute this script function.
*
* @param self Target object.
@@ -515,9 +616,9 @@ public abstract class ScriptFunctionData implements Serializable {
* @throws Throwable if there is an exception/error with the invocation or thrown from it
*/
Object invoke(final ScriptFunction fn, final Object self, final Object... arguments) throws Throwable {
- final MethodHandle mh = getGenericInvoker();
- final Object selfObj = convertThisObject(self);
- final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
+ final MethodHandle mh = getGenericInvoker(fn.getScope());
+ final Object selfObj = convertThisObject(self);
+ final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
DebuggerSupport.notifyInvoke(mh);
@@ -571,7 +672,7 @@ public abstract class ScriptFunctionData implements Serializable {
}
Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable {
- final MethodHandle mh = getGenericConstructor();
+ final MethodHandle mh = getGenericConstructor(fn.getScope());
final Object[] args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
DebuggerSupport.notifyInvoke(mh);
@@ -690,24 +791,6 @@ public abstract class ScriptFunctionData implements Serializable {
}
/**
- * Adapts the method handle so its return type is {@code Object}. If the handle's return type is already
- * {@code Object}, the handle is returned unchanged.
- *
- * @param mh the handle to adapt
- * @return the adapted handle
- */
- private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) {
- final MethodType type = mh.type();
- return (type.returnType() == Object.class) ? mh : MH.asType(mh, type.changeReturnType(Object.class));
- }
-
- private void ensureConstructor(final CompiledFunction inv) {
- if (!inv.hasConstructor()) {
- inv.setConstructor(composeConstructor(inv.getInvoker()));
- }
- }
-
- /**
* Heuristic to figure out if the method handle has a callee argument. If it's type is
* {@code (ScriptFunction, ...)}, then we'll assume it has a callee argument. We need this as
* the constructor above is not passed this information, and can't just blindly assume it's false
@@ -719,8 +802,18 @@ public abstract class ScriptFunctionData implements Serializable {
* @return true if the method handle expects a callee, false otherwise
*/
protected static boolean needsCallee(final MethodHandle mh) {
- final MethodType type = mh.type();
- return (type.parameterCount() > 0 && type.parameterType(0) == ScriptFunction.class);
+ return needsCallee(mh.type());
+ }
+
+ static boolean needsCallee(final MethodType type) {
+ final int length = type.parameterCount();
+
+ if (length == 0) {
+ return false;
+ }
+
+ final Class<?> param0 = type.parameterType(0);
+ return param0 == ScriptFunction.class || param0 == boolean.class && length > 1 && type.parameterType(1) == ScriptFunction.class;
}
/**
@@ -731,10 +824,21 @@ public abstract class ScriptFunctionData implements Serializable {
* @return true if vararg
*/
protected static boolean isVarArg(final MethodHandle mh) {
- final MethodType type = mh.type();
+ return isVarArg(mh.type());
+ }
+
+ static boolean isVarArg(final MethodType type) {
return type.parameterType(type.parameterCount() - 1).isArray();
}
+ /**
+ * Is this ScriptFunction declared in a dynamic context
+ * @return true if in dynamic context, false if not or irrelevant
+ */
+ public boolean inDynamicContext() {
+ return false;
+ }
+
@SuppressWarnings("unused")
private static Object[] bindVarArgs(final Object[] array1, final Object[] array2) {
if (array2 == null) {
@@ -755,12 +859,22 @@ public abstract class ScriptFunctionData implements Serializable {
return concat;
}
- @SuppressWarnings("unused")
- private static Object newFilter(final Object result, final Object allocation) {
- return (result instanceof ScriptObject || !JSType.isPrimitive(result))? result : allocation;
- }
-
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, name, MH.type(rtype, types));
}
+
+ /**
+ * This class is used to hold the generic invoker and generic constructor pair. It is structured in this way since
+ * most functions will never use them, so this way ScriptFunctionData only pays storage cost for one null reference
+ * to the GenericInvokers object, instead of two null references for the two method handles.
+ */
+ private static final class GenericInvokers {
+ volatile MethodHandle invoker;
+ volatile MethodHandle constructor;
+ }
+
+ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ code = new LinkedList<>();
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
index 52c98d40..b2a54beb 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.runtime;
import java.security.CodeSource;
-import java.security.ProtectionDomain;
/**
* Responsible for loading script generated classes.
@@ -50,7 +49,7 @@ final class ScriptLoader extends NashornLoader {
}
@Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
checkPackageAccess(name);
if (name.startsWith(NASHORN_PKG_PREFIX)) {
return context.getSharedLoader().loadClass(name);
diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java
index deae803e..c3eca18f 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -25,11 +25,16 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
@@ -37,8 +42,13 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
+import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -55,18 +65,18 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -90,29 +100,35 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
* </ul>
*/
-public abstract class ScriptObject implements PropertyAccess {
+public abstract class ScriptObject implements PropertyAccess, Cloneable {
/** __proto__ special property name inside object literals. ES6 draft. */
public static final String PROTO_PROPERTY_NAME = "__proto__";
/** Search fall back routine name for "no such method" */
- static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__";
+ public static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__";
/** Search fall back routine name for "no such property" */
- static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
+ public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
/** Per ScriptObject flag - is this a scope object? */
- public static final int IS_SCOPE = 0b0000_0001;
+ public static final int IS_SCOPE = 1 << 0;
/** Per ScriptObject flag - is this an array object? */
- public static final int IS_ARRAY = 0b0000_0010;
+ public static final int IS_ARRAY = 1 << 1;
/** Per ScriptObject flag - is this an arguments object? */
- public static final int IS_ARGUMENTS = 0b0000_0100;
+ public static final int IS_ARGUMENTS = 1 << 2;
/** Is length property not-writable? */
- public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
+ public static final int IS_LENGTH_NOT_WRITABLE = 1 << 3;
+
+ /** Is this a builtin object? */
+ public static final int IS_BUILTIN = 1 << 4;
- /** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
+ /**
+ * Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
+ * {@link ScriptObject#objectSpill} when full
+ */
public static final int SPILL_RATE = 8;
/** Map to property information and accessor functions. Ordered by insertion. */
@@ -124,26 +140,42 @@ public abstract class ScriptObject implements PropertyAccess {
/** Object flags. */
private int flags;
- /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
- public Object[] spill;
+ /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
+ protected long[] primitiveSpill;
+
+ /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */
+ protected Object[] objectSpill;
+
+ /**
+ * Number of elements in the spill. This may be less than the spill array lengths, if not all of
+ * the allocated memory is in use
+ */
+ private int spillLength;
/** Indexed array data. */
private ArrayData arrayData;
- /** Method handle to retrive prototype of this object */
- public static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
- static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
- static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+ /** Method handle to retrieve prototype of this object */
+ public static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class);
- static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
- static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
- static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
- static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
+ static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
+ static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
+ static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class);
- private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
- private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
+ private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
+ private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
+ private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
- private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
+ private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
+
+ /** Method handle for getting the array data */
+ public static final Call GET_ARRAY = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArray", ArrayData.class);
+
+ /** Method handle for getting the property map - debugging purposes */
+ public static final Call GET_MAP = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getMap", PropertyMap.class);
+
+ /** Method handle for setting the array data */
+ public static final Call SET_ARRAY = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArray", void.class, ArrayData.class);
/** Method handle for getting a function argument at a given index. Used from MapCreator */
public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
@@ -154,15 +186,33 @@ public abstract class ScriptObject implements PropertyAccess {
/** Method handle for getting the proto of a ScriptObject */
public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
+ /** Method handle for getting the proto of a ScriptObject */
+ public static final Call GET_PROTO_DEPTH = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
+
/** Method handle for setting the proto of a ScriptObject */
- public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
+ public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
/** Method handle for setting the proto of a ScriptObject after checking argument */
public static final Call SET_PROTO_FROM_LITERAL = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
/** Method handle for setting the user accessors of a ScriptObject */
+ //TODO fastpath this
public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
+ static final MethodHandle[] SET_SLOW = new MethodHandle[] {
+ findOwnMH_V("set", void.class, Object.class, int.class, int.class),
+ findOwnMH_V("set", void.class, Object.class, long.class, int.class),
+ findOwnMH_V("set", void.class, Object.class, double.class, int.class),
+ findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
+ };
+
+ /** Method handle to reset the map of this ScriptObject */
+ public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
+
+ static final MethodHandle CAS_MAP = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
+ static final MethodHandle EXTENSION_CHECK = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
+ static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
+
/**
* Constructor
*/
@@ -179,7 +229,6 @@ public abstract class ScriptObject implements PropertyAccess {
if (Context.DEBUG) {
ScriptObject.count++;
}
-
this.arrayData = ArrayData.EMPTY_ARRAY;
this.setMap(map == null ? PropertyMap.newMap() : map);
}
@@ -194,16 +243,50 @@ public abstract class ScriptObject implements PropertyAccess {
* @param map intial {@link PropertyMap}
*/
protected ScriptObject(final ScriptObject proto, final PropertyMap map) {
- if (Context.DEBUG) {
- ScriptObject.count++;
- }
-
- this.arrayData = ArrayData.EMPTY_ARRAY;
- this.setMap(map == null ? PropertyMap.newMap() : map);
+ this(map);
this.proto = proto;
}
/**
+ * Constructor used to instantiate spill properties directly. Used from
+ * SpillObjectCreator.
+ *
+ * @param map property maps
+ * @param primitiveSpill primitive spills
+ * @param objectSpill reference spills
+ */
+ public ScriptObject(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+ this(map);
+ this.primitiveSpill = primitiveSpill;
+ this.objectSpill = objectSpill;
+ assert primitiveSpill.length == objectSpill.length : " primitive spill pool size is not the same length as object spill pool size";
+ this.spillLength = spillAllocationLength(primitiveSpill.length);
+ }
+
+ /**
+ * Check whether this is a global object
+ * @return true if global
+ */
+ protected boolean isGlobal() {
+ return false;
+ }
+
+ private static int alignUp(final int size, final int alignment) {
+ return size + alignment - 1 & ~(alignment - 1);
+ }
+
+ /**
+ * Given a number of properties, return the aligned to SPILL_RATE
+ * buffer size required for the smallest spill pool needed to
+ * house them
+ * @param nProperties number of properties
+ * @return property buffer length, a multiple of SPILL_RATE
+ */
+ public static int spillAllocationLength(final int nProperties) {
+ return alignUp(nProperties, SPILL_RATE);
+ }
+
+ /**
* Copy all properties from the source object with their receiver bound to the source.
* This function was known as mergeMap
*
@@ -223,29 +306,44 @@ public abstract class ScriptObject implements PropertyAccess {
PropertyMap newMap = this.getMap();
for (final Property property : properties) {
- final String key = property.getKey();
- final Property oldProp = newMap.findProperty(key);
- if (oldProp == null) {
- if (property instanceof UserAccessorProperty) {
- // Note: we copy accessor functions to this object which is semantically different from binding.
- final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
- newMap = newMap.addPropertyNoHistory(prop);
- } else {
- newMap = newMap.addPropertyBind((AccessorProperty)property, source);
- }
+ newMap = addBoundProperty(newMap, source, property);
+ }
+
+ this.setMap(newMap);
+ }
+
+ /**
+ * Add a bound property from {@code source}, using the interim property map {@code propMap}, and return the
+ * new interim property map.
+ *
+ * @param propMap the property map
+ * @param source the source object
+ * @param property the property to be added
+ * @return the new property map
+ */
+ protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
+ PropertyMap newMap = propMap;
+ final String key = property.getKey();
+ final Property oldProp = newMap.findProperty(key);
+ if (oldProp == null) {
+ if (property instanceof UserAccessorProperty) {
+ // Note: we copy accessor functions to this object which is semantically different from binding.
+ final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
+ newMap = newMap.addPropertyNoHistory(prop);
} else {
- // See ECMA section 10.5 Declaration Binding Instantiation
- // step 5 processing each function declaration.
- if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
- if (oldProp instanceof UserAccessorProperty ||
- !(oldProp.isWritable() && oldProp.isEnumerable())) {
- throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
- }
+ newMap = newMap.addPropertyBind((AccessorProperty)property, source);
+ }
+ } else {
+ // See ECMA section 10.5 Declaration Binding Instantiation
+ // step 5 processing each function declaration.
+ if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
+ if (oldProp instanceof UserAccessorProperty ||
+ !(oldProp.isWritable() && oldProp.isEnumerable())) {
+ throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
}
}
}
-
- this.setMap(newMap);
+ return newMap;
}
/**
@@ -386,10 +484,10 @@ public abstract class ScriptObject implements PropertyAccess {
if (property instanceof UserAccessorProperty) {
return global.newAccessorDescriptor(
- (get != null) ?
+ get != null ?
get :
UNDEFINED,
- (set != null) ?
+ set != null ?
set :
UNDEFINED,
configurable,
@@ -430,6 +528,17 @@ public abstract class ScriptObject implements PropertyAccess {
}
/**
+ * Invalidate any existing global constant method handles that may exist for {@code key}.
+ * @param key the property name
+ */
+ protected void invalidateGlobalConstant(final String key) {
+ final GlobalConstants globalConstants = getGlobalConstants();
+ if (globalConstants != null) {
+ globalConstants.delete(key);
+ }
+ }
+
+ /**
* ECMA 8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)
*
* @param key the property key
@@ -444,6 +553,8 @@ public abstract class ScriptObject implements PropertyAccess {
final Object current = getOwnPropertyDescriptor(key);
final String name = JSType.toString(key);
+ invalidateGlobalConstant(key);
+
if (current == UNDEFINED) {
if (isExtensible()) {
// add a new own property
@@ -456,12 +567,12 @@ public abstract class ScriptObject implements PropertyAccess {
}
return false;
}
+
// modifying an existing property
- final PropertyDescriptor currentDesc = (PropertyDescriptor) current;
+ final PropertyDescriptor currentDesc = (PropertyDescriptor)current;
final PropertyDescriptor newDesc = desc;
- if (newDesc.type() == PropertyDescriptor.GENERIC &&
- ! newDesc.has(CONFIGURABLE) && ! newDesc.has(ENUMERABLE)) {
+ if (newDesc.type() == PropertyDescriptor.GENERIC && !newDesc.has(CONFIGURABLE) && !newDesc.has(ENUMERABLE)) {
// every descriptor field is absent
return true;
}
@@ -471,7 +582,7 @@ public abstract class ScriptObject implements PropertyAccess {
return true;
}
- if (! currentDesc.isConfigurable()) {
+ if (!currentDesc.isConfigurable()) {
if (newDesc.has(CONFIGURABLE) && newDesc.isConfigurable()) {
// not configurable can not be made configurable
if (reject) {
@@ -494,10 +605,11 @@ public abstract class ScriptObject implements PropertyAccess {
Property property = getMap().findProperty(key);
if (currentDesc.type() == PropertyDescriptor.DATA &&
- (newDesc.type() == PropertyDescriptor.DATA || newDesc.type() == PropertyDescriptor.GENERIC)) {
- if (! currentDesc.isConfigurable() && ! currentDesc.isWritable()) {
+ (newDesc.type() == PropertyDescriptor.DATA ||
+ newDesc.type() == PropertyDescriptor.GENERIC)) {
+ if (!currentDesc.isConfigurable() && !currentDesc.isWritable()) {
if (newDesc.has(WRITABLE) && newDesc.isWritable() ||
- newDesc.has(VALUE) && ! ScriptRuntime.sameValue(currentDesc.getValue(), newDesc.getValue())) {
+ newDesc.has(VALUE) && !ScriptRuntime.sameValue(currentDesc.getValue(), newDesc.getValue())) {
if (reject) {
throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
}
@@ -506,11 +618,20 @@ public abstract class ScriptObject implements PropertyAccess {
}
final boolean newValue = newDesc.has(VALUE);
- final Object value = newValue? newDesc.getValue() : currentDesc.getValue();
+ final Object value = newValue ? newDesc.getValue() : currentDesc.getValue();
+
if (newValue && property != null) {
// Temporarily clear flags.
property = modifyOwnProperty(property, 0);
- set(key, value, false);
+ set(key, value, 0);
+ //this might change the map if we change types of the property
+ //hence we need to read it again. note that we should probably
+ //have the setter return the new property throughout and in
+ //general respect Property return values from modify and add
+ //functions - which we don't seem to do at all here :-(
+ //There is already a bug filed to generify PropertyAccess so we
+ //can have the setter return e.g. a Property
+ property = getMap().findProperty(key);
}
if (property == null) {
@@ -524,23 +645,22 @@ public abstract class ScriptObject implements PropertyAccess {
} else if (currentDesc.type() == PropertyDescriptor.ACCESSOR &&
(newDesc.type() == PropertyDescriptor.ACCESSOR ||
newDesc.type() == PropertyDescriptor.GENERIC)) {
- if (! currentDesc.isConfigurable()) {
- if (newDesc.has(PropertyDescriptor.GET) && ! ScriptRuntime.sameValue(currentDesc.getGetter(), newDesc.getGetter()) ||
- newDesc.has(PropertyDescriptor.SET) && ! ScriptRuntime.sameValue(currentDesc.getSetter(), newDesc.getSetter())) {
+ if (!currentDesc.isConfigurable()) {
+ if (newDesc.has(PropertyDescriptor.GET) && !ScriptRuntime.sameValue(currentDesc.getGetter(), newDesc.getGetter()) ||
+ newDesc.has(PropertyDescriptor.SET) && !ScriptRuntime.sameValue(currentDesc.getSetter(), newDesc.getSetter())) {
if (reject) {
throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
}
return false;
}
}
-
// New set the new features.
modifyOwnProperty(property, propFlags,
newDesc.has(GET) ? newDesc.getGetter() : currentDesc.getGetter(),
newDesc.has(SET) ? newDesc.getSetter() : currentDesc.getSetter());
} else {
// changing descriptor type
- if (! currentDesc.isConfigurable()) {
+ if (!currentDesc.isConfigurable()) {
// not configurable can not be made configurable
if (reject) {
throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
@@ -552,7 +672,7 @@ public abstract class ScriptObject implements PropertyAccess {
// Preserve only configurable and enumerable from current desc
// if those are not overridden in the new property descriptor.
- boolean value = newDesc.has(CONFIGURABLE)? newDesc.isConfigurable() : currentDesc.isConfigurable();
+ boolean value = newDesc.has(CONFIGURABLE) ? newDesc.isConfigurable() : currentDesc.isConfigurable();
if (!value) {
propFlags |= Property.NOT_CONFIGURABLE;
}
@@ -565,7 +685,7 @@ public abstract class ScriptObject implements PropertyAccess {
if (type == PropertyDescriptor.DATA) {
// get writable from the new descriptor
value = newDesc.has(WRITABLE) && newDesc.isWritable();
- if (! value) {
+ if (!value) {
propFlags |= Property.NOT_WRITABLE;
}
@@ -602,7 +722,8 @@ public abstract class ScriptObject implements PropertyAccess {
public void defineOwnProperty(final int index, final Object value) {
assert isValidArrayIndex(index) : "invalid array index";
final long longIndex = ArrayIndex.toLongIndex(index);
- setValueAtArrayIndex(longIndex, index, value, false);
+ doesNotHaveEnsureDelete(longIndex, getArray().length(), false);
+ setArray(getArray().ensure(longIndex).set(index,value, false));
}
private void checkIntegerKey(final String key) {
@@ -666,7 +787,7 @@ public abstract class ScriptObject implements PropertyAccess {
* @return FindPropertyData or null if not found.
*/
public final FindProperty findProperty(final String key, final boolean deep) {
- return findProperty(key, deep, false, this);
+ return findProperty(key, deep, this);
}
/**
@@ -683,16 +804,11 @@ public abstract class ScriptObject implements PropertyAccess {
*
* @param key Property key.
* @param deep Whether the search should look up proto chain.
- * @param stopOnNonScope should a deep search stop on the first non-scope object?
* @param start the object on which the lookup was originally initiated
*
* @return FindPropertyData or null if not found.
*/
- FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
- // if doing deep search, stop search on the first non-scope object if asked to do so
- if (stopOnNonScope && start != this && !isScope()) {
- return null;
- }
+ FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
final PropertyMap selfMap = getMap();
final Property property = selfMap.findProperty(key);
@@ -704,7 +820,7 @@ public abstract class ScriptObject implements PropertyAccess {
if (deep) {
final ScriptObject myProto = getProto();
if (myProto != null) {
- return myProto.findProperty(key, deep, stopOnNonScope, start);
+ return myProto.findProperty(key, deep, start);
}
}
@@ -733,6 +849,19 @@ public abstract class ScriptObject implements PropertyAccess {
return false;
}
+ private SwitchPoint findBuiltinSwitchPoint(final String key) {
+ for (ScriptObject myProto = getProto(); myProto != null; myProto = myProto.getProto()) {
+ final Property prop = myProto.getMap().findProperty(key);
+ if (prop != null) {
+ final SwitchPoint sp = prop.getBuiltinSwitchPoint();
+ if (sp != null && !sp.hasBeenInvalidated()) {
+ return sp;
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Add a new property to the object.
* <p>
@@ -761,9 +890,7 @@ public abstract class ScriptObject implements PropertyAccess {
* @return New property.
*/
public final Property addOwnProperty(final String key, final int propertyFlags, final Object value) {
- final Property property = addSpillProperty(key, propertyFlags);
- property.setObjectValue(this, this, value, false);
- return property;
+ return addSpillProperty(key, propertyFlags, value, true);
}
/**
@@ -777,10 +904,8 @@ public abstract class ScriptObject implements PropertyAccess {
*/
public final Property addOwnProperty(final Property newProperty) {
PropertyMap oldMap = getMap();
-
while (true) {
final PropertyMap newMap = oldMap.addProperty(newProperty);
-
if (!compareAndSetMap(oldMap, newMap)) {
oldMap = getMap();
final Property oldProperty = oldMap.findProperty(newProperty.getKey());
@@ -798,7 +923,8 @@ public abstract class ScriptObject implements PropertyAccess {
// Erase the property field value with undefined. If the property is defined
// by user-defined accessors, we don't want to call the setter!!
if (!(property instanceof UserAccessorProperty)) {
- property.setObjectValue(this, this, UNDEFINED, false);
+ assert property != null;
+ property.setValue(this, this, UNDEFINED, false);
}
}
@@ -825,13 +951,37 @@ public abstract class ScriptObject implements PropertyAccess {
} else {
// delete getter and setter function references so that we don't leak
if (property instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty) property;
- setSpill(uc.getGetterSlot(), null);
- setSpill(uc.getSetterSlot(), null);
+ ((UserAccessorProperty)property).setAccessors(this, getMap(), null);
}
+
+ invalidateGlobalConstant(property.getKey());
return true;
}
}
+
+ }
+
+ /**
+ * Fast initialization functions for ScriptFunctions that are strict, to avoid
+ * creating setters that probably aren't used. Inject directly into the spill pool
+ * the defaults for "arguments" and "caller"
+ *
+ * @param key property key
+ * @param propertyFlags flags
+ * @param getter getter for {@link UserAccessorProperty}, null if not present or N/A
+ * @param setter setter for {@link UserAccessorProperty}, null if not present or N/A
+ */
+ protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
+ final int slot = spillLength;
+ ensureSpillSize(spillLength); //arguments=slot0, caller=slot0
+ objectSpill[slot] = new UserAccessorProperty.Accessors(getter, setter);
+ final PropertyMap oldMap = getMap();
+ Property newProperty;
+ PropertyMap newMap;
+ do {
+ newProperty = new UserAccessorProperty(key, propertyFlags, slot);
+ newMap = oldMap.addProperty(newProperty);
+ } while (!compareAndSetMap(oldMap, newMap));
}
/**
@@ -846,19 +996,27 @@ public abstract class ScriptObject implements PropertyAccess {
*/
public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
Property newProperty;
+
if (oldProperty instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty) oldProperty;
- final int getterSlot = uc.getGetterSlot();
- final int setterSlot = uc.getSetterSlot();
- setSpill(getterSlot, getter);
- setSpill(setterSlot, setter);
+ final UserAccessorProperty uc = (UserAccessorProperty)oldProperty;
+ final int slot = uc.getSlot();
- // if just flipping getter and setter with new functions, no need to change property or map
- if (uc.flags == propertyFlags) {
- return oldProperty;
+ assert uc.getLocalType() == Object.class;
+ if (slot >= spillLength) {
+ uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+ } else {
+ final UserAccessorProperty.Accessors gs = uc.getAccessors(this); //this crashes
+ if (gs == null) {
+ uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+ } else {
+ //reuse existing getter setter for speed
+ gs.set(getter, setter);
+ if (uc.getFlags() == propertyFlags) {
+ return oldProperty;
+ }
+ }
}
-
- newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot);
+ newProperty = new UserAccessorProperty(uc.getKey(), propertyFlags, slot);
} else {
// erase old property value and create new user accessor property
erasePropertyValue(oldProperty);
@@ -889,6 +1047,10 @@ public abstract class ScriptObject implements PropertyAccess {
* @return new property
*/
private Property modifyOwnProperty(final Property oldProperty, final Property newProperty) {
+ if (oldProperty == newProperty) {
+ return newProperty; //nop
+ }
+
assert newProperty.getKey().equals(oldProperty.getKey()) : "replacing property with different key";
PropertyMap oldMap = getMap();
@@ -925,8 +1087,8 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- private static int getIntValue(final FindProperty find) {
- final MethodHandle getter = find.getGetter(int.class);
+ private static int getIntValue(final FindProperty find, final int programPoint) {
+ final MethodHandle getter = find.getGetter(int.class, programPoint, null);
if (getter != null) {
try {
return (int)getter.invokeExact((Object)find.getGetterReceiver());
@@ -937,11 +1099,11 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- return ObjectClassGenerator.UNDEFINED_INT;
+ return UNDEFINED_INT;
}
- private static long getLongValue(final FindProperty find) {
- final MethodHandle getter = find.getGetter(long.class);
+ private static long getLongValue(final FindProperty find, final int programPoint) {
+ final MethodHandle getter = find.getGetter(long.class, programPoint, null);
if (getter != null) {
try {
return (long)getter.invokeExact((Object)find.getGetterReceiver());
@@ -952,11 +1114,11 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- return ObjectClassGenerator.UNDEFINED_LONG;
+ return UNDEFINED_LONG;
}
- private static double getDoubleValue(final FindProperty find) {
- final MethodHandle getter = find.getGetter(double.class);
+ private static double getDoubleValue(final FindProperty find, final int programPoint) {
+ final MethodHandle getter = find.getGetter(double.class, programPoint, null);
if (getter != null) {
try {
return (double)getter.invokeExact((Object)find.getGetterReceiver());
@@ -967,7 +1129,7 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- return ObjectClassGenerator.UNDEFINED_DOUBLE;
+ return UNDEFINED_DOUBLE;
}
/**
@@ -1040,7 +1202,7 @@ public abstract class ScriptObject implements PropertyAccess {
* @param value the value to write at the given index
*/
public void setArgument(final int key, final Object value) {
- set(key, value, false);
+ set(key, value, 0);
}
/**
@@ -1073,14 +1235,12 @@ public abstract class ScriptObject implements PropertyAccess {
* @param newMap Replacement map.
* @return true if the operation succeeded.
*/
- protected synchronized final boolean compareAndSetMap(final PropertyMap oldMap, final PropertyMap newMap) {
- final boolean update = oldMap == this.map;
-
- if (update) {
+ protected final boolean compareAndSetMap(final PropertyMap oldMap, final PropertyMap newMap) {
+ if (oldMap == this.map) {
this.map = newMap;
+ return true;
}
-
- return update;
+ return false;
}
/**
@@ -1092,10 +1252,24 @@ public abstract class ScriptObject implements PropertyAccess {
}
/**
+ * Get the proto of a specific depth
+ * @param n depth
+ * @return proto at given depth
+ */
+ public final ScriptObject getProto(final int n) {
+ assert n > 0;
+ ScriptObject p = getProto();
+ for (int i = n; i-- > 0;) {
+ p = p.getProto();
+ }
+ return p;
+ }
+
+ /**
* Set the __proto__ of an object.
* @param newProto new __proto__ to set.
*/
- public synchronized final void setProto(final ScriptObject newProto) {
+ public final void setProto(final ScriptObject newProto) {
final ScriptObject oldProto = proto;
if (oldProto != newProto) {
@@ -1124,6 +1298,14 @@ public abstract class ScriptObject implements PropertyAccess {
}
/**
+ * Invoked from generated bytecode to initialize the prototype of object literals to the global Object prototype.
+ * @param obj the object literal that needs to have its prototype initialized to the global Object prototype.
+ */
+ public static void setGlobalObjectProto(final ScriptObject obj) {
+ obj.setInitialProto(Global.objectPrototype());
+ }
+
+ /**
* Set the __proto__ of an object with checks.
* This is the built-in operation [[SetPrototypeOf]]
* See ES6 draft spec: 9.1.2 [[SetPrototypeOf]] (V)
@@ -1132,8 +1314,9 @@ public abstract class ScriptObject implements PropertyAccess {
*/
public final void setPrototypeOf(final Object newProto) {
if (newProto == null || newProto instanceof ScriptObject) {
- if (!isExtensible()) {
+ if (! isExtensible()) {
// okay to set same proto again - even if non-extensible
+
if (newProto == getProto()) {
return;
}
@@ -1180,22 +1363,44 @@ public abstract class ScriptObject implements PropertyAccess {
* @param all True if to include non-enumerable keys.
* @return Array of keys.
*/
- public String[] getOwnKeys(final boolean all) {
+ public final String[] getOwnKeys(final boolean all) {
+ return getOwnKeys(all, null);
+ }
+
+ /**
+ * return an array of own property keys associated with the object.
+ *
+ * @param all True if to include non-enumerable keys.
+ * @param nonEnumerable set of non-enumerable properties seen already.Used
+ to filter out shadowed, but enumerable properties from proto children.
+ * @return Array of keys.
+ */
+ protected String[] getOwnKeys(final boolean all, final Set<String> nonEnumerable) {
final List<Object> keys = new ArrayList<>();
final PropertyMap selfMap = this.getMap();
final ArrayData array = getArray();
- final long length = array.length();
- for (long i = 0; i < length; i = array.nextIndex(i)) {
- if (array.has((int)i)) {
- keys.add(JSType.toString(i));
- }
+ for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
+ keys.add(JSType.toString(iter.next().longValue()));
}
for (final Property property : selfMap.getProperties()) {
- if (all || property.isEnumerable()) {
- keys.add(property.getKey());
+ final boolean enumerable = property.isEnumerable();
+ final String key = property.getKey();
+ if (all) {
+ keys.add(key);
+ } else if (enumerable) {
+ // either we don't have non-enumerable filter set or filter set
+ // does not contain the current property.
+ if (nonEnumerable == null || !nonEnumerable.contains(key)) {
+ keys.add(key);
+ }
+ } else {
+ // store this non-enumerable property for later proto walk
+ if (nonEnumerable != null) {
+ nonEnumerable.add(key);
+ }
}
}
@@ -1279,16 +1484,15 @@ public abstract class ScriptObject implements PropertyAccess {
*/
public ScriptObject preventExtensions() {
PropertyMap oldMap = getMap();
-
- while (true) {
- final PropertyMap newMap = getMap().preventExtensions();
-
- if (!compareAndSetMap(oldMap, newMap)) {
- oldMap = getMap();
- } else {
- return this;
- }
+ while (!compareAndSetMap(oldMap, getMap().preventExtensions())) {
+ oldMap = getMap();
}
+
+ //invalidate any fast array setters
+ final ArrayData array = getArray();
+ assert array != null;
+ setArray(ArrayData.preventExtension(array));
+ return this;
}
/**
@@ -1299,7 +1503,7 @@ public abstract class ScriptObject implements PropertyAccess {
* @return true if array
*/
public static boolean isArray(final Object obj) {
- return (obj instanceof ScriptObject) && ((ScriptObject)obj).isArray();
+ return obj instanceof ScriptObject && ((ScriptObject)obj).isArray();
}
/**
@@ -1337,18 +1541,35 @@ public abstract class ScriptObject implements PropertyAccess {
*
* @return {@code true} if 'length' property is non-writable
*/
- public final boolean isLengthNotWritable() {
+ public boolean isLengthNotWritable() {
return (flags & IS_LENGTH_NOT_WRITABLE) != 0;
}
/**
- * Flag this object as having non-writable length property
+ * Flag this object as having non-writable length property.
*/
public void setIsLengthNotWritable() {
flags |= IS_LENGTH_NOT_WRITABLE;
}
/**
+ * Get the {@link ArrayData}, for this ScriptObject, ensuring it is of a type
+ * that can handle elementType
+ * @param elementType elementType
+ * @return array data
+ */
+ public final ArrayData getArray(final Class<?> elementType) {
+ if (elementType == null) {
+ return arrayData;
+ }
+ final ArrayData newArrayData = arrayData.convert(elementType);
+ if (newArrayData != arrayData) {
+ arrayData = newArrayData;
+ }
+ return newArrayData;
+ }
+
+ /**
* Get the {@link ArrayData} for this ScriptObject if it is an array
* @return array data
*/
@@ -1446,6 +1667,21 @@ public abstract class ScriptObject implements PropertyAccess {
}
/**
+ * Tag this script object as built in
+ */
+ public final void setIsBuiltin() {
+ flags |= IS_BUILTIN;
+ }
+
+ /**
+ * Check if this script object is built in
+ * @return true if build in
+ */
+ public final boolean isBuiltin() {
+ return (flags & IS_BUILTIN) != 0;
+ }
+
+ /**
* Clears the properties from a ScriptObject
* (java.util.Map-like method to help ScriptObjectMirror implementation)
*
@@ -1540,7 +1776,8 @@ public abstract class ScriptObject implements PropertyAccess {
*/
public Object put(final Object key, final Object value, final boolean strict) {
final Object oldValue = get(key);
- set(key, value, strict);
+ final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
+ set(key, value, scriptObjectFlags);
return oldValue;
}
@@ -1553,8 +1790,9 @@ public abstract class ScriptObject implements PropertyAccess {
* @param strict strict mode or not
*/
public void putAll(final Map<?, ?> otherMap, final boolean strict) {
+ final int scriptObjectFlags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
- set(entry.getKey(), entry.getValue(), strict);
+ set(entry.getKey(), entry.getValue(), scriptObjectFlags);
}
}
@@ -1629,11 +1867,11 @@ public abstract class ScriptObject implements PropertyAccess {
return c > 2 ? findGetMethod(desc, request, operator) : findGetIndexMethod(desc, request);
case "setProp":
case "setElem":
- return c > 2 ? findSetMethod(desc, request) : findSetIndexMethod(desc);
+ return c > 2 ? findSetMethod(desc, request) : findSetIndexMethod(desc, request);
case "call":
return findCallMethod(desc, request);
case "new":
- return findNewMethod(desc);
+ return findNewMethod(desc, request);
case "callMethod":
return findCallMethodMethod(desc, request);
default:
@@ -1645,10 +1883,11 @@ public abstract class ScriptObject implements PropertyAccess {
* Find the appropriate New method for an invoke dynamic call.
*
* @param desc The invoke dynamic call site descriptor.
+ * @param request The link request
*
* @return GuardedInvocation to be invoked at call site.
*/
- protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+ protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return notAFunction();
}
@@ -1722,12 +1961,12 @@ public abstract class ScriptObject implements PropertyAccess {
return methodHandle;
}
final int listIndex = depth - 1; // We don't need 0-deep walker
- MethodHandle filter = listIndex < protoFilters.size() ? protoFilters.get(listIndex) : null;
+ MethodHandle filter = listIndex < PROTO_FILTERS.size() ? PROTO_FILTERS.get(listIndex) : null;
- if(filter == null) {
+ if (filter == null) {
filter = addProtoFilter(GETPROTO, depth - 1);
- protoFilters.add(null);
- protoFilters.set(listIndex, filter);
+ PROTO_FILTERS.add(null);
+ PROTO_FILTERS.set(listIndex, filter);
}
return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
@@ -1743,66 +1982,110 @@ public abstract class ScriptObject implements PropertyAccess {
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
- final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+
+ String name;
+ name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ if (NashornCallSiteDescriptor.isApplyToCall(desc)) {
+ if (Global.isBuiltinFunctionPrototypeApply()) {
+ name = "call";
+ }
+ }
+
if (request.isCallSiteUnstable() || hasWithScope()) {
return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
}
final FindProperty find = findProperty(name, true);
- MethodHandle methodHandle;
+ MethodHandle mh;
if (find == null) {
- if ("getProp".equals(operator)) {
+ switch (operator) {
+ case "getElem": // getElem only gets here if element name is constant, so treat it like a property access
+ case "getProp":
return noSuchProperty(desc, request);
- } else if ("getMethod".equals(operator)) {
+ case "getMethod":
return noSuchMethod(desc, request);
- } else if ("getElem".equals(operator)) {
- return createEmptyGetter(desc, name);
+ default:
+ throw new AssertionError(operator); // never invoked with any other operation
+ }
+ }
+
+ final GlobalConstants globalConstants = getGlobalConstants();
+ if (globalConstants != null) {
+ final GuardedInvocation cinv = globalConstants.findGetMethod(find, this, desc);
+ if (cinv != null) {
+ return cinv;
}
- throw new AssertionError(); // never invoked with any other operation
}
final Class<?> returnType = desc.getMethodType().returnType();
- final Property property = find.getProperty();
- methodHandle = find.getGetter(returnType);
+ final Property property = find.getProperty();
+
+ final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ?
+ NashornCallSiteDescriptor.getProgramPoint(desc) :
+ UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+ mh = find.getGetter(returnType, programPoint, request);
// Get the appropriate guard for this callsite and property.
- final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
+ final MethodHandle guard = NashornGuards.getGuard(this, property, desc, explicitInstanceOfCheck);
final ScriptObject owner = find.getOwner();
+ final Class<ClassCastException> exception = explicitInstanceOfCheck ? null : ClassCastException.class;
- if (methodHandle != null) {
- assert methodHandle.type().returnType().equals(returnType);
- if (find.isSelf()) {
- return new GuardedInvocation(methodHandle, guard);
- }
+ final SwitchPoint protoSwitchPoint;
- if (!property.hasGetterFunction(owner)) {
+ if (mh == null) {
+ mh = Lookup.emptyGetter(returnType);
+ protoSwitchPoint = getProtoSwitchPoint(name, owner);
+ } else if (!find.isSelf()) {
+ assert mh.type().returnType().equals(returnType) :
+ "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
+ if (!(property instanceof UserAccessorProperty)) {
// Add a filter that replaces the self object with the prototype owning the property.
- methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
+ mh = addProtoFilter(mh, find.getProtoChainLength());
}
- return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
+ protoSwitchPoint = getProtoSwitchPoint(name, owner);
+ } else {
+ protoSwitchPoint = null;
}
- assert !NashornCallSiteDescriptor.isFastScope(desc);
- return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
+ assert OBJECT_FIELDS_ONLY || guard != null : "we always need a map guard here";
+
+ final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
+ return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
}
- private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
- final boolean isMethod) {
+ private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
+ Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
- final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
+ final MethodHandle guard = getScriptObjectGuard(desc.getMethodType(), true);
return new GuardedInvocation(invoker, guard);
}
@SuppressWarnings("unused")
private Object megamorphicGet(final String key, final boolean isMethod) {
final FindProperty find = findProperty(key, true);
-
if (find != null) {
return find.getObjectValue();
}
- return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
+ return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
+ }
+
+ // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
+ @SuppressWarnings("unused")
+ private void declareAndSet(final String key, final Object value) {
+ final PropertyMap oldMap = getMap();
+ final FindProperty find = findProperty(key, false);
+ assert find != null;
+
+ final Property property = find.getProperty();
+ assert property != null;
+ assert property.needsDeclaration();
+
+ final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
+ setMap(newMap);
+ set(key, value, 0);
}
/**
@@ -1814,31 +2097,48 @@ public abstract class ScriptObject implements PropertyAccess {
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
- return findGetIndexMethod(desc.getMethodType());
- }
-
- /**
- * Find the appropriate GETINDEX method for an invoke dynamic call.
- *
- * @param callType the call site method type
- * @return GuardedInvocation to be invoked at call site.
- */
- private static GuardedInvocation findGetIndexMethod(final MethodType callType) {
- final Class<?> returnClass = callType.returnType();
- final Class<?> keyClass = callType.parameterType(1);
+ final MethodType callType = desc.getMethodType();
+ final Class<?> returnType = callType.returnType();
+ final Class<?> returnClass = returnType.isPrimitive() ? returnType : Object.class;
+ final Class<?> keyClass = callType.parameterType(1);
+ final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
- String name = "get";
+ final String name;
if (returnClass.isPrimitive()) {
//turn e.g. get with a double into getDouble
final String returnTypeName = returnClass.getName();
- name += Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
+ name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
+ } else {
+ name = "get";
}
- return new GuardedInvocation(findOwnMH(name, returnClass, keyClass), getScriptObjectGuard(callType));
+ final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc);
+ return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
+ }
+
+ private static MethodHandle getScriptObjectGuard(final MethodType type, final boolean explicitInstanceOfCheck) {
+ return ScriptObject.class.isAssignableFrom(type.parameterType(0)) ? null : NashornGuards.getScriptObjectGuard(explicitInstanceOfCheck);
}
- private static MethodHandle getScriptObjectGuard(final MethodType type) {
- return ScriptObject.class.isAssignableFrom(type.parameterType(0)) ? null : NashornGuards.getScriptObjectGuard();
+ /**
+ * Find a handle for a getIndex method
+ * @param returnType return type for getter
+ * @param name name
+ * @param elementType index type for getter
+ * @param desc call site descriptor
+ * @return method handle for getter
+ */
+ protected MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
+ if (!returnType.isPrimitive()) {
+ return findOwnMH_V(getClass(), name, returnType, elementType);
+ }
+
+ return MH.insertArguments(
+ findOwnMH_V(getClass(), name, returnType, elementType, int.class),
+ 2,
+ NashornCallSiteDescriptor.isOptimistic(desc) ?
+ NashornCallSiteDescriptor.getProgramPoint(desc) :
+ INVALID_PROGRAM_POINT);
}
/**
@@ -1856,7 +2156,7 @@ public abstract class ScriptObject implements PropertyAccess {
}
for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
- ScriptObject parent = obj.getProto();
+ final ScriptObject parent = obj.getProto();
parent.getMap().addListener(name, obj.getMap());
}
@@ -1873,11 +2173,13 @@ public abstract class ScriptObject implements PropertyAccess {
*/
protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
if (request.isCallSiteUnstable() || hasWithScope()) {
return findMegaMorphicSetMethod(desc, name);
}
- final boolean scope = isScope();
+ final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+
/*
* If doing property set on a scope object, we should stop proto search on the first
* non-scope object. Without this, for example, when assigning "toString" on global scope,
@@ -1885,111 +2187,83 @@ public abstract class ScriptObject implements PropertyAccess {
*
* toString = function() { print("global toString"); } // don't affect Object.prototype.toString
*/
- FindProperty find = findProperty(name, true, scope, this);
+ FindProperty find = findProperty(name, true, this);
// If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
- if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
+ if (find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
// We should still check if inherited data property is not writable
if (isExtensible() && !find.getProperty().isWritable()) {
- return createEmptySetMethod(desc, "property.not.writable", false);
+ return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
+ }
+ // Otherwise, forget the found property unless this is a scope callsite and the owner is a scope object as well.
+ if (!NashornCallSiteDescriptor.isScope(desc) || !find.getOwner().isScope()) {
+ find = null;
}
- // Otherwise, forget the found property
- find = null;
}
if (find != null) {
- if(!find.getProperty().isWritable()) {
+ if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
+ if (NashornCallSiteDescriptor.isScope(desc) && find.getProperty().isLexicalBinding()) {
+ throw typeError("assign.constant", name); // Overwriting ES6 const should throw also in non-strict mode.
+ }
// Existing, non-writable property
- return createEmptySetMethod(desc, "property.not.writable", true);
+ return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
}
} else {
- if (! isExtensible()) {
- return createEmptySetMethod(desc, "object.non.extensible", false);
+ if (!isExtensible()) {
+ return createEmptySetMethod(desc, explicitInstanceOfCheck, "object.non.extensible", false);
}
}
- return new SetMethodCreator(this, find, desc).createGuardedInvocation();
- }
+ final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(findBuiltinSwitchPoint(name));
- private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, String strictErrorMessage, boolean canBeFastScope) {
- final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if (NashornCallSiteDescriptor.isStrict(desc)) {
- throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this)));
- }
- assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
- return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
- }
-
- @SuppressWarnings("unused")
- private static void setField(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final MethodHandle setter, final Object self, final Object value) throws Throwable {
- final ScriptObject obj = (ScriptObject)self;
- final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
- if (!obj.isExtensible()) {
- if (isStrict) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
- }
- } else if (obj.compareAndSetMap(oldMap, newMap)) {
- setter.invokeExact(self, value);
- } else {
- obj.set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
+ final GlobalConstants globalConstants = getGlobalConstants();
+ if (globalConstants != null) {
+ final GuardedInvocation cinv = globalConstants.findSetMethod(find, this, inv, desc, request);
+ if (cinv != null) {
+ return cinv;
+ }
}
+
+ return inv;
}
- @SuppressWarnings("unused")
- private static void setSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
- final ScriptObject obj = (ScriptObject)self;
- if (obj.trySetSpill(desc, oldMap, newMap, value)) {
- obj.spill[index] = value;
- }
+ private GlobalConstants getGlobalConstants() {
+ // Avoid hitting getContext() which might be costly for a non-Global unless needed.
+ return GlobalConstants.GLOBAL_ONLY && !isGlobal() ? null : getContext().getGlobalConstants();
}
- private boolean trySetSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
- final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
- if (!isExtensible() && isStrict) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(this));
- } else if (compareAndSetMap(oldMap, newMap)) {
- return true;
- } else {
- set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
- return false;
+ private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String strictErrorMessage, final boolean canBeFastScope) {
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ if (NashornCallSiteDescriptor.isStrict(desc)) {
+ throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString(this));
}
+ assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
+ return new GuardedInvocation(
+ Lookup.EMPTY_SETTER,
+ NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
+ getProtoSwitchPoint(name, null),
+ explicitInstanceOfCheck ? null : ClassCastException.class);
}
@SuppressWarnings("unused")
- private static void setSpillWithNew(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
- final ScriptObject obj = (ScriptObject)self;
- final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
-
- if (!obj.isExtensible()) {
- if (isStrict) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
- }
- } else if (obj.compareAndSetMap(oldMap, newMap)) {
- obj.spill = new Object[SPILL_RATE];
- obj.spill[index] = value;
+ private boolean extensionCheck(final boolean isStrict, final String name) {
+ if (isExtensible()) {
+ return true; //go on and do the set. this is our guard
+ } else if (isStrict) {
+ //throw an error for attempting to do the set in strict mode
+ throw typeError("object.non.extensible", name, ScriptRuntime.safeToString(this));
} else {
- obj.set(desc.getNameToken(2), value, isStrict);
+ //not extensible, non strict - this is a nop
+ return false;
}
}
- @SuppressWarnings("unused")
- private static void setSpillWithGrow(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final int newLength, final Object self, final Object value) {
- final ScriptObject obj = (ScriptObject)self;
- final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
-
- if (!obj.isExtensible()) {
- if (isStrict) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
- }
- } else if (obj.compareAndSetMap(oldMap, newMap)) {
- final int oldLength = obj.spill.length;
- final Object[] newSpill = new Object[newLength];
- System.arraycopy(obj.spill, 0, newSpill, 0, oldLength);
- obj.spill = newSpill;
- obj.spill[index] = value;
- } else {
- obj.set(desc.getNameToken(2), value, isStrict);
- }
+ private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
+ final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
+ //never bother with ClassCastExceptionGuard for megamorphic callsites
+ final GuardedInvocation inv = findSetIndexMethod(getClass(), desc, false, type);
+ return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
}
@SuppressWarnings("unused")
@@ -2001,34 +2275,38 @@ public abstract class ScriptObject implements PropertyAccess {
return sobj;
}
- private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
- final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
- final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
- return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
- }
-
- private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) { // array, index, value
- return findSetIndexMethod(desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
+ /**
+ * Lookup function for the set index method, available for subclasses as well, e.g. {@link NativeArray}
+ * provides special quick accessor linkage for continuous arrays that are represented as Java arrays
+ *
+ * @param desc call site descriptor
+ * @param request link request
+ *
+ * @return GuardedInvocation to be invoked at call site.
+ */
+ protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+ return findSetIndexMethod(getClass(), desc, explicitInstanceOfCheck(desc, request), desc.getMethodType());
}
/**
* Find the appropriate SETINDEX method for an invoke dynamic call.
*
+ * @param clazz the receiver class
+ * @param desc the call site descriptor
+ * @param explicitInstanceOfCheck add an explicit instanceof check?
* @param callType the method type at the call site
- * @param isStrict are we in strict mode?
*
* @return GuardedInvocation to be invoked at call site.
*/
- private static GuardedInvocation findSetIndexMethod(final MethodType callType, final boolean isStrict) {
+ private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final MethodType callType) {
assert callType.parameterCount() == 3;
+ final Class<?> keyClass = callType.parameterType(1);
+ final Class<?> valueClass = callType.parameterType(2);
- final Class<?> keyClass = callType.parameterType(1);
- final Class<?> valueClass = callType.parameterType(2);
-
- MethodHandle methodHandle = findOwnMH("set", void.class, keyClass, valueClass, boolean.class);
- methodHandle = MH.insertArguments(methodHandle, 3, isStrict);
+ MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, int.class);
+ methodHandle = MH.insertArguments(methodHandle, 3, NashornCallSiteDescriptor.getFlags(desc));
- return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType));
+ return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
/**
@@ -2046,17 +2324,27 @@ public abstract class ScriptObject implements PropertyAccess {
return noSuchProperty(desc, request);
}
+ final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+
final Object value = find.getObjectValue();
- if (! (value instanceof ScriptFunction)) {
- return createEmptyGetter(desc, name);
+ if (!(value instanceof ScriptFunction)) {
+ return createEmptyGetter(desc, explicitInstanceOfCheck, name);
}
final ScriptFunction func = (ScriptFunction)value;
- final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
+ final Object thiz = scopeCall && func.isStrict() ? UNDEFINED : this;
// TODO: It'd be awesome if we could bind "name" without binding "this".
- return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class,
- func.makeBoundFunction(thiz, new Object[] { name })), 0, Object.class),
- null, NashornGuards.getMapGuard(getMap()));
+ // Since we're binding this we must use an identity guard here.
+ return new GuardedInvocation(
+ MH.dropArguments(
+ MH.constant(
+ ScriptFunction.class,
+ func.makeBoundFunction(thiz, new Object[] { name })),
+ 0,
+ Object.class),
+ NashornGuards.combineGuards(
+ NashornGuards.getIdentityGuard(this),
+ NashornGuards.getMapGuard(getMap(), true)));
}
/**
@@ -2065,29 +2353,44 @@ public abstract class ScriptObject implements PropertyAccess {
* @param request the link request
* @return GuardedInvocation to be invoked at call site.
*/
- @SuppressWarnings("null")
public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) {
- final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
- final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
+ final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
if (find != null) {
- final Object value = find.getObjectValue();
- ScriptFunction func = null;
- MethodHandle methodHandle = null;
+ final Object value = find.getObjectValue();
+ ScriptFunction func = null;
+ MethodHandle mh = null;
if (value instanceof ScriptFunction) {
func = (ScriptFunction)value;
- methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+ mh = getCallMethodHandle(func, desc.getMethodType(), name);
}
- if (methodHandle != null) {
+ if (mh != null) {
+ assert func != null;
if (scopeAccess && func.isStrict()) {
- methodHandle = bindTo(methodHandle, UNDEFINED);
+ mh = bindTo(mh, UNDEFINED);
}
- return new GuardedInvocation(methodHandle,
+
+ return new GuardedInvocation(
+ mh,
+ find.isSelf()?
+ getKnownFunctionPropertyGuardSelf(
+ getMap(),
+ find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
+ func)
+ :
+ //TODO this always does a scriptobject check
+ getKnownFunctionPropertyGuardProto(
+ getMap(),
+ find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
+ find.getProtoChainLength(),
+ func),
getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
- getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
+ //TODO this doesn't need a ClassCastException as guard always checks script object
+ null);
}
}
@@ -2095,51 +2398,64 @@ public abstract class ScriptObject implements PropertyAccess {
throw referenceError("not.defined", name);
}
- return createEmptyGetter(desc, name);
+ return createEmptyGetter(desc, explicitInstanceOfCheck(desc, request), name);
}
/**
* Invoke fall back if a property is not found.
* @param name Name of property.
+ * @param programPoint program point
* @return Result from call.
*/
- protected Object invokeNoSuchProperty(final String name) {
+ protected Object invokeNoSuchProperty(final String name, final int programPoint) {
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
+ Object ret = UNDEFINED;
+
if (find != null) {
final Object func = find.getObjectValue();
if (func instanceof ScriptFunction) {
- return ScriptRuntime.apply((ScriptFunction)func, this, name);
+ ret = ScriptRuntime.apply((ScriptFunction)func, this, name);
}
}
- return UNDEFINED;
+ if (isValid(programPoint)) {
+ throw new UnwarrantedOptimismException(ret, programPoint);
+ }
+
+ return ret;
}
+
/**
* Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
* @param name the method name
* @return the bound function, or undefined
*/
- private Object getNoSuchMethod(final String name) {
+ private Object getNoSuchMethod(final String name, final int programPoint) {
final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
if (find == null) {
- return invokeNoSuchProperty(name);
+ return invokeNoSuchProperty(name, programPoint);
}
final Object value = find.getObjectValue();
- if (! (value instanceof ScriptFunction)) {
+ if (!(value instanceof ScriptFunction)) {
return UNDEFINED;
}
return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name});
}
- private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
+ private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
+ if (NashornCallSiteDescriptor.isOptimistic(desc)) {
+ throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
+ }
+
return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
- getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
+ NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
+ explicitInstanceOfCheck ? null : ClassCastException.class);
}
private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
@@ -2171,7 +2487,7 @@ public abstract class ScriptObject implements PropertyAccess {
@Override
public void remove() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("remove");
}
}
@@ -2183,8 +2499,9 @@ public abstract class ScriptObject implements PropertyAccess {
@Override
protected void init() {
final Set<String> keys = new LinkedHashSet<>();
+ final Set<String> nonEnumerable = new HashSet<>();
for (ScriptObject self = object; self != null; self = self.getProto()) {
- keys.addAll(Arrays.asList(self.getOwnKeys(false)));
+ keys.addAll(Arrays.asList(self.getOwnKeys(false, nonEnumerable)));
}
this.values = keys.toArray(new String[keys.size()]);
}
@@ -2198,8 +2515,9 @@ public abstract class ScriptObject implements PropertyAccess {
@Override
protected void init() {
final ArrayList<Object> valueList = new ArrayList<>();
+ final Set<String> nonEnumerable = new HashSet<>();
for (ScriptObject self = object; self != null; self = self.getProto()) {
- for (final String key : self.getOwnKeys(false)) {
+ for (final String key : self.getOwnKeys(false, nonEnumerable)) {
valueList.add(self.get(key));
}
}
@@ -2213,46 +2531,34 @@ public abstract class ScriptObject implements PropertyAccess {
* @param propertyFlags Property flags.
* @return Added property.
*/
- private Property addSpillProperty(final String key, final int propertyFlags) {
- int fieldCount = getMap().getFieldCount();
- int fieldMaximum = getMap().getFieldMaximum();
- Property property;
+ private Property addSpillProperty(final String key, final int propertyFlags, final Object value, final boolean hasInitialValue) {
+ final PropertyMap propertyMap = getMap();
+ final int fieldSlot = propertyMap.getFreeFieldSlot();
- if (fieldCount < fieldMaximum) {
- property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
+ Property property;
+ if (fieldSlot > -1) {
+ property = hasInitialValue ?
+ new AccessorProperty(key, propertyFlags, fieldSlot, this, value) :
+ new AccessorProperty(key, propertyFlags, getClass(), fieldSlot);
property = addOwnProperty(property);
} else {
- int i = getMap().getSpillLength();
- property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
+ final int spillSlot = propertyMap.getFreeSpillSlot();
+ property = hasInitialValue ?
+ new SpillProperty(key, propertyFlags, spillSlot, this, value) :
+ new SpillProperty(key, propertyFlags, spillSlot);
property = addOwnProperty(property);
- i = property.getSlot();
-
- final int newLength = (i + SPILL_RATE) / SPILL_RATE * SPILL_RATE;
-
- if (spill == null || newLength > spill.length) {
- final Object[] newSpill = new Object[newLength];
-
- if (spill != null) {
- System.arraycopy(spill, 0, newSpill, 0, spill.length);
- }
-
- spill = newSpill;
- }
+ ensureSpillSize(property.getSlot());
}
-
return property;
}
-
/**
* Add a spill entry for the given key.
* @param key Property key.
* @return Setter method handle.
*/
- MethodHandle addSpill(final String key) {
- final Property spillProperty = addSpillProperty(key, 0);
- final Class<?> type = Object.class;
- return spillProperty.getSetter(type, getMap()); //TODO specfields
+ MethodHandle addSpill(final Class<?> type, final String key) {
+ return addSpillProperty(key, 0, null, false).getSetter(OBJECT_FIELDS_ONLY ? Object.class : type, getMap());
}
/**
@@ -2285,9 +2591,8 @@ public abstract class ScriptObject implements PropertyAccess {
* @return method handle with adjusted arguments
*/
public static MethodHandle pairArguments(final MethodHandle methodHandle, final MethodType callType, final Boolean callerVarArg) {
-
final MethodType methodType = methodHandle.type();
- if (methodType.equals(callType)) {
+ if (methodType.equals(callType.changeReturnType(methodType.returnType()))) {
return methodHandle;
}
@@ -2295,8 +2600,18 @@ public abstract class ScriptObject implements PropertyAccess {
final int callCount = callType.parameterCount();
final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
- final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 0 &&
- callType.parameterType(callCount - 1).isArray());
+ final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 &&
+ callType.parameterType(callCount - 1).isArray();
+
+ if (isCalleeVarArg) {
+ return isCallerVarArg ?
+ methodHandle :
+ MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
+ }
+
+ if (isCallerVarArg) {
+ return adaptHandleToVarArgCallSite(methodHandle, callCount);
+ }
if (callCount < parameterCount) {
final int missingArgs = parameterCount - callCount;
@@ -2305,7 +2620,7 @@ public abstract class ScriptObject implements PropertyAccess {
Arrays.fill(fillers, UNDEFINED);
if (isCalleeVarArg) {
- fillers[missingArgs - 1] = new Object[0];
+ fillers[missingArgs - 1] = ScriptRuntime.EMPTY_ARRAY;
}
return MH.insertArguments(
@@ -2314,27 +2629,6 @@ public abstract class ScriptObject implements PropertyAccess {
fillers);
}
- if (isCalleeVarArg) {
- return isCallerVarArg ?
- methodHandle :
- MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
- }
-
- if (isCallerVarArg) {
- final int spreadArgs = parameterCount - callCount + 1;
- return MH.filterArguments(
- MH.asSpreader(
- methodHandle,
- Object[].class,
- spreadArgs),
- callCount - 1,
- MH.insertArguments(
- TRUNCATINGFILTER,
- 0,
- spreadArgs)
- );
- }
-
if (callCount > parameterCount) {
final int discardedArgs = callCount - parameterCount;
@@ -2347,19 +2641,32 @@ public abstract class ScriptObject implements PropertyAccess {
return methodHandle;
}
+ static MethodHandle adaptHandleToVarArgCallSite(final MethodHandle mh, final int callSiteParamCount) {
+ final int spreadArgs = mh.type().parameterCount() - callSiteParamCount + 1;
+ return MH.filterArguments(
+ MH.asSpreader(
+ mh,
+ Object[].class,
+ spreadArgs),
+ callSiteParamCount - 1,
+ MH.insertArguments(
+ TRUNCATINGFILTER,
+ 0,
+ spreadArgs)
+ );
+ }
+
@SuppressWarnings("unused")
private static Object[] truncatingFilter(final int n, final Object[] array) {
final int length = array == null ? 0 : array.length;
if (n == length) {
- return array == null ? new Object[0] : array;
+ return array == null ? ScriptRuntime.EMPTY_ARRAY : array;
}
final Object[] newArray = new Object[n];
if (array != null) {
- for (int i = 0; i < n && i < length; i++) {
- newArray[i] = array[i];
- }
+ System.arraycopy(array, 0, newArray, 0, Math.min(n, length));
}
if (length < n) {
@@ -2379,20 +2686,22 @@ public abstract class ScriptObject implements PropertyAccess {
* @param newLength new length to set
*/
public final void setLength(final long newLength) {
- final long arrayLength = getArray().length();
- if (newLength == arrayLength) {
- return;
- }
+ ArrayData data = getArray();
+ final long arrayLength = data.length();
+ if (newLength == arrayLength) {
+ return;
+ }
- if (newLength > arrayLength) {
- setArray(getArray().ensure(newLength - 1));
- if (getArray().canDelete(arrayLength, (newLength - 1), false)) {
- setArray(getArray().delete(arrayLength, (newLength - 1)));
- }
- return;
- }
+ if (newLength > arrayLength) {
+ data = data.ensure(newLength - 1);
+ if (data.canDelete(arrayLength, newLength - 1, false)) {
+ data = data.delete(arrayLength, newLength - 1);
+ }
+ setArray(data);
+ return;
+ }
- if (newLength < arrayLength) {
+ if (newLength < arrayLength) {
long actualLength = newLength;
// Check for numeric keys in property map and delete them or adjust length, depending on whether
@@ -2414,19 +2723,19 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- setArray(getArray().shrink(actualLength));
- getArray().setLength(actualLength);
+ setArray(data.shrink(actualLength));
+ data.setLength(actualLength);
}
}
- private int getInt(final int index, final String key) {
+ private int getInt(final int index, final String key, final int programPoint) {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
- final FindProperty find = object.findProperty(key, false, false, this);
+ final FindProperty find = object.findProperty(key, false, this);
if (find != null) {
- return getIntValue(find);
+ return getIntValue(find, programPoint);
}
}
@@ -2437,77 +2746,78 @@ public abstract class ScriptObject implements PropertyAccess {
final ArrayData array = object.getArray();
if (array.has(index)) {
- return array.getInt(index);
+ return isValid(programPoint) ?
+ array.getIntOptimistic(index, programPoint) :
+ array.getInt(index);
}
}
} else {
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getIntValue(find);
+ return getIntValue(find, programPoint);
}
}
- return JSType.toInt32(invokeNoSuchProperty(key));
+ return JSType.toInt32(invokeNoSuchProperty(key, programPoint));
}
@Override
- public int getInt(final Object key) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
+ public int getInt(final Object key, final int programPoint) {
+ final Object primitiveKey = JSType.toPrimitive(key, String.class);
+ final int index = getArrayIndex(primitiveKey);
+ final ArrayData array = getArray();
if (array.has(index)) {
- return array.getInt(index);
+ return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
}
- return getInt(index, JSType.toString(primitiveKey));
+ return getInt(index, JSType.toString(primitiveKey), programPoint);
}
@Override
- public int getInt(final double key) {
- final int index = getArrayIndex(key);
+ public int getInt(final double key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getInt(index);
+ return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
}
- return getInt(index, JSType.toString(key));
+ return getInt(index, JSType.toString(key), programPoint);
}
@Override
- public int getInt(final long key) {
- final int index = getArrayIndex(key);
+ public int getInt(final long key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getInt(index);
+ return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
}
- return getInt(index, JSType.toString(key));
+ return getInt(index, JSType.toString(key), programPoint);
}
@Override
- public int getInt(final int key) {
- final int index = getArrayIndex(key);
+ public int getInt(final int key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getInt(index);
+ return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
}
- return getInt(index, JSType.toString(key));
+ return getInt(index, JSType.toString(key), programPoint);
}
- private long getLong(final int index, final String key) {
+ private long getLong(final int index, final String key, final int programPoint) {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
- final FindProperty find = object.findProperty(key, false, false, this);
-
+ final FindProperty find = object.findProperty(key, false, this);
if (find != null) {
- return getLongValue(find);
+ return getLongValue(find, programPoint);
}
}
@@ -2518,77 +2828,78 @@ public abstract class ScriptObject implements PropertyAccess {
final ArrayData array = object.getArray();
if (array.has(index)) {
- return array.getLong(index);
+ return isValid(programPoint) ?
+ array.getLongOptimistic(index, programPoint) :
+ array.getLong(index);
}
}
} else {
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getLongValue(find);
+ return getLongValue(find, programPoint);
}
}
- return JSType.toLong(invokeNoSuchProperty(key));
+ return JSType.toLong(invokeNoSuchProperty(key, programPoint));
}
@Override
- public long getLong(final Object key) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
+ public long getLong(final Object key, final int programPoint) {
+ final Object primitiveKey = JSType.toPrimitive(key, String.class);
+ final int index = getArrayIndex(primitiveKey);
+ final ArrayData array = getArray();
if (array.has(index)) {
- return array.getLong(index);
+ return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
}
- return getLong(index, JSType.toString(primitiveKey));
+ return getLong(index, JSType.toString(primitiveKey), programPoint);
}
@Override
- public long getLong(final double key) {
- final int index = getArrayIndex(key);
+ public long getLong(final double key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getLong(index);
+ return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
}
- return getLong(index, JSType.toString(key));
+ return getLong(index, JSType.toString(key), programPoint);
}
@Override
- public long getLong(final long key) {
- final int index = getArrayIndex(key);
+ public long getLong(final long key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getLong(index);
+ return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
}
- return getLong(index, JSType.toString(key));
+ return getLong(index, JSType.toString(key), programPoint);
}
@Override
- public long getLong(final int key) {
- final int index = getArrayIndex(key);
+ public long getLong(final int key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getLong(index);
+ return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key);
}
- return getLong(index, JSType.toString(key));
+ return getLong(index, JSType.toString(key), programPoint);
}
- private double getDouble(final int index, final String key) {
+ private double getDouble(final int index, final String key, final int programPoint) {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
- final FindProperty find = object.findProperty(key, false, false, this);
-
+ final FindProperty find = object.findProperty(key, false, this);
if (find != null) {
- return getDoubleValue(find);
+ return getDoubleValue(find, programPoint);
}
}
@@ -2599,74 +2910,76 @@ public abstract class ScriptObject implements PropertyAccess {
final ArrayData array = object.getArray();
if (array.has(index)) {
- return array.getDouble(index);
+ return isValid(programPoint) ?
+ array.getDoubleOptimistic(index, programPoint) :
+ array.getDouble(index);
}
}
} else {
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getDoubleValue(find);
+ return getDoubleValue(find, programPoint);
}
}
- return JSType.toNumber(invokeNoSuchProperty(key));
+ return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT));
}
@Override
- public double getDouble(final Object key) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
+ public double getDouble(final Object key, final int programPoint) {
+ final Object primitiveKey = JSType.toPrimitive(key, String.class);
+ final int index = getArrayIndex(primitiveKey);
+ final ArrayData array = getArray();
if (array.has(index)) {
- return array.getDouble(index);
+ return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
}
- return getDouble(index, JSType.toString(primitiveKey));
+ return getDouble(index, JSType.toString(primitiveKey), programPoint);
}
@Override
- public double getDouble(final double key) {
- final int index = getArrayIndex(key);
+ public double getDouble(final double key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getDouble(index);
+ return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
}
- return getDouble(index, JSType.toString(key));
+ return getDouble(index, JSType.toString(key), programPoint);
}
@Override
- public double getDouble(final long key) {
- final int index = getArrayIndex(key);
+ public double getDouble(final long key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getDouble(index);
+ return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
}
- return getDouble(index, JSType.toString(key));
+ return getDouble(index, JSType.toString(key), programPoint);
}
@Override
- public double getDouble(final int key) {
- final int index = getArrayIndex(key);
+ public double getDouble(final int key, final int programPoint) {
+ final int index = getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
- return array.getDouble(index);
+ return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
}
- return getDouble(index, JSType.toString(key));
+ return getDouble(index, JSType.toString(key), programPoint);
}
private Object get(final int index, final String key) {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
if (object.getMap().containsArrayKeys()) {
- final FindProperty find = object.findProperty(key, false, false, this);
+ final FindProperty find = object.findProperty(key, false, this);
if (find != null) {
return find.getObjectValue();
@@ -2691,14 +3004,14 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
- return invokeNoSuchProperty(key);
+ return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
}
@Override
public Object get(final Object key) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
+ final Object primitiveKey = JSType.toPrimitive(key, String.class);
+ final int index = getArrayIndex(primitiveKey);
+ final ArrayData array = getArray();
if (array.has(index)) {
return array.getObject(index);
@@ -2743,65 +3056,115 @@ public abstract class ScriptObject implements PropertyAccess {
return get(index, JSType.toString(key));
}
- /**
- * Handle when an array doesn't have a slot - possibly grow and/or convert array.
- *
- * @param index key as index
- * @param value element value
- * @param strict are we in strict mode
- */
- private void doesNotHave(final int index, final Object value, final boolean strict) {
- final long longIndex = ArrayIndex.toLongIndex(index);
+ private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
if (getMap().containsArrayKeys()) {
- final String key = JSType.toString(longIndex);
+ final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
+ if (find != null) {
+ setObject(find, callSiteFlags, key, value);
+ return true;
+ }
+ }
+ return false;
+ }
+ private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final int callSiteFlags) {
+ if (getMap().containsArrayKeys()) {
+ final String key = JSType.toString(longIndex);
+ final FindProperty find = findProperty(key, true);
if (find != null) {
- setObject(find, strict, key, value);
- return;
+ setObject(find, callSiteFlags, key, value);
+ return true;
}
}
+ return false;
+ }
- setValueAtArrayIndex(longIndex, index, value, strict);
+ private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
+ if (getMap().containsArrayKeys()) {
+ final String key = JSType.toString(longIndex);
+ final FindProperty find = findProperty(key, true);
+ if (find != null) {
+ setObject(find, callSiteFlags, key, value);
+ return true;
+ }
+ }
+ return false;
}
- /**
- * Handle when an array doesn't have a slot - possibly grow and/or convert array.
- *
- * @param index key as index
- * @param value element value
- * @param strict are we in strict mode
- */
- private void setValueAtArrayIndex(final long longIndex, final int index, final Object value, final boolean strict) {
- final long oldLength = getArray().length();
+ private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final int callSiteFlags) {
+ if (getMap().containsArrayKeys()) {
+ final String key = JSType.toString(longIndex);
+ final FindProperty find = findProperty(key, true);
+ if (find != null) {
+ setObject(find, callSiteFlags, key, value);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //value agnostic
+ private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
if (longIndex >= oldLength) {
if (!isExtensible()) {
- if (strict) {
- throw typeError("object.non.extensible", JSType.toString(index), ScriptRuntime.safeToString(this));
+ if (isStrictFlag(callSiteFlags)) {
+ throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
}
- return;
+ return true;
}
setArray(getArray().ensure(longIndex));
}
+ return false;
+ }
- if (value instanceof Integer) {
- setArray(getArray().set(index, (int)value, strict));
- } else if (value instanceof Long) {
- setArray(getArray().set(index, (long)value, strict));
- } else if (value instanceof Double) {
- setArray(getArray().set(index, (double)value, strict));
- } else {
+ private void doesNotHaveEnsureDelete(final long longIndex, final long oldLength, final boolean strict) {
+ if (longIndex > oldLength) {
+ ArrayData array = getArray();
+ if (array.canDelete(oldLength, longIndex - 1, strict)) {
+ array = array.delete(oldLength, longIndex - 1);
+ }
+ setArray(array);
+ }
+ }
+
+ private void doesNotHave(final int index, final int value, final int callSiteFlags) {
+ final long oldLength = getArray().length();
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+ final boolean strict = isStrictFlag(callSiteFlags);
setArray(getArray().set(index, value, strict));
+ doesNotHaveEnsureDelete(longIndex, oldLength, strict);
}
+ }
- if (longIndex > oldLength) {
- ArrayData array = getArray();
+ private void doesNotHave(final int index, final long value, final int callSiteFlags) {
+ final long oldLength = getArray().length();
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+ final boolean strict = isStrictFlag(callSiteFlags);
+ setArray(getArray().set(index, value, strict));
+ doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+ }
+ }
- if (array.canDelete(oldLength, (longIndex - 1), strict)) {
- array = array.delete(oldLength, (longIndex - 1));
- }
+ private void doesNotHave(final int index, final double value, final int callSiteFlags) {
+ final long oldLength = getArray().length();
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+ final boolean strict = isStrictFlag(callSiteFlags);
+ setArray(getArray().set(index, value, strict));
+ doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+ }
+ }
- setArray(array);
+ private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
+ final long oldLength = getArray().length();
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
+ final boolean strict = isStrictFlag(callSiteFlags);
+ setArray(getArray().set(index, value, strict));
+ doesNotHaveEnsureDelete(longIndex, oldLength, strict);
}
}
@@ -2809,32 +3172,51 @@ public abstract class ScriptObject implements PropertyAccess {
* This is the most generic of all Object setters. Most of the others use this in some form.
* TODO: should be further specialized
*
- * @param find found property
- * @param strict are we in strict mode
- * @param key property key
- * @param value property value
+ * @param find found property
+ * @param callSiteFlags callsite flags
+ * @param key property key
+ * @param value property value
*/
- public final void setObject(final FindProperty find, final boolean strict, final String key, final Object value) {
+ public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) {
FindProperty f = find;
- if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty) && !isScope()) {
- // Setting a property should not modify the property in prototype unless this is a scope object.
- f = null;
+ invalidateGlobalConstant(key);
+
+ if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
+ final boolean isScope = isScopeFlag(callSiteFlags);
+ // If the start object of the find is not this object it means the property was found inside a
+ // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
+ // to the 'with' object.
+ // Note that although a 'set' operation involving a with statement follows scope rules outside
+ // the 'with' expression (the 'set' operation is performed on the owning prototype if it exists),
+ // it follows non-scope rules inside the 'with' expression (set is performed on the top level object).
+ // This is why we clear the callsite flags and FindProperty in the forward call to the 'with' object.
+ if (isScope && f.getSelf() != this) {
+ f.getSelf().setObject(null, 0, key, value);
+ return;
+ }
+ // Setting a property should not modify the property in prototype unless this is a scope callsite
+ // and the owner is a scope object as well (with the exception of 'with' statement handled above).
+ if (!isScope || !f.getOwner().isScope()) {
+ f = null;
+ }
}
if (f != null) {
if (!f.getProperty().isWritable()) {
- if (strict) {
+ if (isScopeFlag(callSiteFlags) && f.getProperty().isLexicalBinding()) {
+ throw typeError("assign.constant", key); // Overwriting ES6 const should throw also in non-strict mode.
+ }
+ if (isStrictFlag(callSiteFlags)) {
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
}
-
return;
}
- f.setObjectValue(value, strict);
+ f.setValue(value, isStrictFlag(callSiteFlags));
} else if (!isExtensible()) {
- if (strict) {
+ if (isStrictFlag(callSiteFlags)) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
@@ -2846,311 +3228,323 @@ public abstract class ScriptObject implements PropertyAccess {
}
assert sobj != null : "no parent global object in scope";
}
- sobj.spill(key, value);
+ //this will unbox any Number object to its primitive type in case the
+ //property supports primitive types, so it doesn't matter that it comes
+ //in as an Object.
+ sobj.addSpillProperty(key, 0, value, true);
}
}
- private void spill(final String key, final Object value) {
- addSpillProperty(key, 0).setObjectValue(this, this, value, false);
- }
-
-
@Override
- public void set(final Object key, final int value, final boolean strict) {
+ public void set(final Object key, final int value, final int callSiteFlags) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(primitiveKey);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final Object key, final long value, final boolean strict) {
+ public void set(final Object key, final long value, final int callSiteFlags) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(primitiveKey);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final Object key, final double value, final boolean strict) {
+ public void set(final Object key, final double value, final int callSiteFlags) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(primitiveKey);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final Object key, final Object value, final boolean strict) {
+ public void set(final Object key, final Object value, final int callSiteFlags) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(primitiveKey);
- setObject(findProperty(propName, true), strict, propName, value);
+ setObject(findProperty(propName, true), callSiteFlags, propName, value);
}
@Override
- public void set(final double key, final int value, final boolean strict) {
+ public void set(final double key, final int value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final double key, final long value, final boolean strict) {
+ public void set(final double key, final long value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final double key, final double value, final boolean strict) {
+ public void set(final double key, final double value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final double key, final Object value, final boolean strict) {
+ public void set(final double key, final Object value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, value);
+ setObject(findProperty(propName, true), callSiteFlags, propName, value);
}
@Override
- public void set(final long key, final int value, final boolean strict) {
+ public void set(final long key, final int value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final long key, final long value, final boolean strict) {
+ public void set(final long key, final long value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final long key, final double value, final boolean strict) {
+ public void set(final long key, final double value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final long key, final Object value, final boolean strict) {
+ public void set(final long key, final Object value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, value);
+ setObject(findProperty(propName, true), callSiteFlags, propName, value);
}
@Override
- public void set(final int key, final int value, final boolean strict) {
+ public void set(final int key, final int value, final int callSiteFlags) {
final int index = getArrayIndex(key);
-
if (isValidArrayIndex(index)) {
if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
-
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final int key, final long value, final boolean strict) {
+ public void set(final int key, final long value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final int key, final double value, final boolean strict) {
+ public void set(final int key, final double value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+ setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
}
@Override
- public void set(final int key, final Object value, final boolean strict) {
+ public void set(final int key, final Object value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
- if (getArray().has(index)) {
- setArray(getArray().set(index, value, strict));
+ final ArrayData data = getArray();
+ if (data.has(index)) {
+ setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
- doesNotHave(index, value, strict);
+ doesNotHave(index, value, callSiteFlags);
}
return;
}
final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), strict, propName, value);
+ setObject(findProperty(propName, true), callSiteFlags, propName, value);
}
@Override
public boolean has(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), true);
}
@@ -3188,7 +3582,7 @@ public abstract class ScriptObject implements PropertyAccess {
@Override
public boolean hasOwnProperty(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
+ final int index = getArrayIndex(primitiveKey);
return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), false);
}
@@ -3211,7 +3605,7 @@ public abstract class ScriptObject implements PropertyAccess {
}
private boolean hasOwnArrayProperty(final int index) {
- return getArray().has(index) || (getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false));
+ return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
}
@Override
@@ -3226,7 +3620,6 @@ public abstract class ScriptObject implements PropertyAccess {
}
return false;
}
-
return deleteObject(JSType.toObject(key), strict);
}
@@ -3264,9 +3657,9 @@ public abstract class ScriptObject implements PropertyAccess {
@Override
public boolean delete(final Object key, final boolean strict) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
+ final Object primitiveKey = JSType.toPrimitive(key, String.class);
+ final int index = getArrayIndex(primitiveKey);
+ final ArrayData array = getArray();
if (array.has(index)) {
if (array.canDelete(index, strict)) {
@@ -3301,6 +3694,31 @@ public abstract class ScriptObject implements PropertyAccess {
}
/**
+ * Return a shallow copy of this ScriptObject.
+ * @return a shallow copy.
+ */
+ public final ScriptObject copy() {
+ try {
+ return clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected ScriptObject clone() throws CloneNotSupportedException {
+ final ScriptObject clone = (ScriptObject) super.clone();
+ if (objectSpill != null) {
+ clone.objectSpill = objectSpill.clone();
+ if (primitiveSpill != null) {
+ clone.primitiveSpill = primitiveSpill.clone();
+ }
+ }
+ clone.arrayData = arrayData.copy();
+ return clone;
+ }
+
+ /**
* Make a new UserAccessorProperty property. getter and setter functions are stored in
* this ScriptObject and slot values are used in property object.
*
@@ -3311,60 +3729,91 @@ public abstract class ScriptObject implements PropertyAccess {
* @return the newly created UserAccessorProperty
*/
protected final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
- final UserAccessorProperty property = getMap().newUserAccessors(key, propertyFlags);
- setSpill(property.getGetterSlot(), getter);
- setSpill(property.getSetterSlot(), setter);
-
- return property;
+ final UserAccessorProperty uc = getMap().newUserAccessors(key, propertyFlags);
+ //property.getSetter(Object.class, getMap());
+ uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+ return uc;
}
- /**
- * Write a value to a spill slot
- * @param slot the slot index
- * @param value the value
- */
- protected final void setSpill(final int slot, final Object value) {
- if (spill == null) {
- // create new spill.
- spill = new Object[Math.max(slot + 1, SPILL_RATE)];
- } else if (slot >= spill.length) {
- // grow spill as needed
- final Object[] newSpill = new Object[slot + 1];
- System.arraycopy(spill, 0, newSpill, 0, spill.length);
- spill = newSpill;
+ Object ensureSpillSize(final int slot) {
+ if (slot < spillLength) {
+ return this;
+ }
+ final int newLength = alignUp(slot + 1, SPILL_RATE);
+ final Object[] newObjectSpill = new Object[newLength];
+ final long[] newPrimitiveSpill = OBJECT_FIELDS_ONLY ? null : new long[newLength];
+
+ if (objectSpill != null) {
+ System.arraycopy(objectSpill, 0, newObjectSpill, 0, spillLength);
+ if (!OBJECT_FIELDS_ONLY) {
+ System.arraycopy(primitiveSpill, 0, newPrimitiveSpill, 0, spillLength);
+ }
}
- spill[slot] = value;
+ this.primitiveSpill = newPrimitiveSpill;
+ this.objectSpill = newObjectSpill;
+ this.spillLength = newLength;
+
+ return this;
}
- /**
- * Get a value from a spill slot
- * @param slot the slot index
- * @return the value in the spill slot with the given index
- */
- protected Object getSpill(final int slot) {
- return spill != null && slot < spill.length ? spill[slot] : null;
+ private static MethodHandle findOwnMH_V(final Class<? extends ScriptObject> clazz, final String name, final Class<?> rtype, final Class<?>... types) {
+ // TODO: figure out how can it work for NativeArray$Prototype etc.
+ return MH.findVirtual(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- final Class<?> own = ScriptObject.class;
- final MethodType mt = MH.type(rtype, types);
- try {
- return MH.findStatic(MethodHandles.lookup(), own, name, mt);
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), own, name, mt);
+ private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ return findOwnMH_V(ScriptObject.class, name, rtype, types);
+ }
+
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
+ }
+
+ private static MethodHandle getKnownFunctionPropertyGuardSelf(final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
+ return MH.insertArguments(KNOWNFUNCPROPGUARDSELF, 1, map, getter, func);
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
+ if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
+ try {
+ return getter.invokeExact(self) == func;
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
}
+
+ return false;
+ }
+
+ private static MethodHandle getKnownFunctionPropertyGuardProto(final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
+ return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
}
- private static MethodHandle getKnownFunctionPropertyGuard(final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
- return MH.insertArguments(KNOWNFUNCPROPGUARD, 1, map, getter, where, func);
+ private static ScriptObject getProto(final ScriptObject self, final int depth) {
+ ScriptObject proto = self;
+ for (int d = 0; d < depth; d++) {
+ proto = proto.getProto();
+ if (proto == null) {
+ return null;
+ }
+ }
+
+ return proto;
}
@SuppressWarnings("unused")
- private static boolean knownFunctionPropertyGuard(final Object self, final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
+ private static boolean knownFunctionPropertyGuardProto(final Object self, final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
+ final ScriptObject proto = getProto((ScriptObject)self, depth);
+ if (proto == null) {
+ return false;
+ }
try {
- return getter.invokeExact(where) == func;
+ return getter.invokeExact((Object)proto) == func;
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
diff --git a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index 6df047d8..e927d4fc 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -27,13 +27,14 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.SwitchPoint;
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.Iterator;
@@ -45,9 +46,12 @@ import java.util.Objects;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.codegen.ApplySpecialization;
+import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.ir.debug.JSONWriter;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeObject;
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -81,9 +85,6 @@ public final class ScriptRuntime {
/** Method handle used to enter a {@code with} scope at runtime. */
public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class);
- /** Method handle used to exit a {@code with} scope at runtime. */
- public static final Call CLOSE_WITH = staticCallNoLookup(ScriptRuntime.class, "closeWith", ScriptObject.class, ScriptObject.class);
-
/**
* Method used to place a scope's variable into the Global scope, which has to be done for the
* properties declared at outermost script level.
@@ -108,6 +109,16 @@ public final class ScriptRuntime {
public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
/**
+ * Throws a reference error for an undefined variable.
+ */
+ public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
+
+ /**
+ * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
+ */
+ public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);
+
+ /**
* Converts a switch tag value to a simple integer. deflt value if it can't.
*
* @param tag Switch statement tag value.
@@ -121,7 +132,6 @@ public final class ScriptRuntime {
return (int)d;
}
}
-
return deflt;
}
@@ -169,7 +179,7 @@ public final class ScriptRuntime {
// But we don't need to -- all we need is the right class name
// of the corresponding primitive wrapper type.
- final JSType type = JSType.of(self);
+ final JSType type = JSType.ofNoFunction(self);
switch (type) {
case BOOLEAN:
@@ -189,7 +199,6 @@ public final class ScriptRuntime {
className = "Undefined";
break;
case OBJECT:
- case FUNCTION:
if (self instanceof ScriptObject) {
className = ((ScriptObject)self).getClassName();
} else if (self instanceof JSObject) {
@@ -271,7 +280,7 @@ public final class ScriptRuntime {
private final int length;
private int index;
- RangeIterator(int length) {
+ RangeIterator(final int length) {
this.length = length;
}
@@ -287,7 +296,7 @@ public final class ScriptRuntime {
@Override
public void remove() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("remove");
}
}
@@ -325,7 +334,7 @@ public final class ScriptRuntime {
@Override
public void remove() {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("remove");
}
};
}
@@ -384,6 +393,15 @@ public final class ScriptRuntime {
}
/**
+ * Throws a reference error for an undefined variable.
+ *
+ * @param name the variable name
+ */
+ public static void throwReferenceError(final String name) {
+ throw referenceError("not.defined", name);
+ }
+
+ /**
* Call a script function as a constructor with given args.
*
* @param target ScriptFunction object.
@@ -409,8 +427,8 @@ public final class ScriptRuntime {
* @return true if both objects have the same value
*/
public static boolean sameValue(final Object x, final Object y) {
- final JSType xType = JSType.of(x);
- final JSType yType = JSType.of(y);
+ final JSType xType = JSType.ofNoFunction(x);
+ final JSType yType = JSType.ofNoFunction(y);
if (xType != yType) {
return false;
@@ -429,7 +447,7 @@ public final class ScriptRuntime {
}
// checking for xVal == -0.0 and yVal == +0.0 or vice versa
- if (xVal == 0.0 && (Double.doubleToLongBits(xVal) != Double.doubleToLongBits(yVal))) {
+ if (xVal == 0.0 && Double.doubleToLongBits(xVal) != Double.doubleToLongBits(yVal)) {
return false;
}
@@ -440,7 +458,7 @@ public final class ScriptRuntime {
return x.equals(y);
}
- return (x == y);
+ return x == y;
}
/**
@@ -453,7 +471,7 @@ public final class ScriptRuntime {
* @return JSON string representation of AST of the supplied code
*/
public static String parse(final String code, final String name, final boolean includeLoc) {
- return JSONWriter.parse(Context.getContextTrusted().getEnv(), code, name, includeLoc);
+ return JSONWriter.parse(Context.getContextTrusted(), code, name, includeLoc);
}
/**
@@ -466,7 +484,8 @@ public final class ScriptRuntime {
}
/**
- * Entering a {@code with} node requires new scope. This is the implementation
+ * Entering a {@code with} node requires new scope. This is the implementation. When exiting the with statement,
+ * use {@link ScriptObject#getProto()} on the scope.
*
* @param scope existing scope
* @param expression expression in with
@@ -481,6 +500,17 @@ public final class ScriptRuntime {
throw typeError(global, "cant.apply.with.to.null");
}
+ if (expression instanceof ScriptObjectMirror) {
+ final Object unwrapped = ScriptObjectMirror.unwrap(expression, global);
+ if (unwrapped instanceof ScriptObject) {
+ return new WithObject(scope, (ScriptObject)unwrapped);
+ }
+ // foreign ScriptObjectMirror
+ final ScriptObject exprObj = global.newObject();
+ NativeObject.bindAllProperties(exprObj, (ScriptObjectMirror)expression);
+ return new WithObject(scope, exprObj);
+ }
+
final Object wrappedExpr = JSType.toScriptObject(global, expression);
if (wrappedExpr instanceof ScriptObject) {
return new WithObject(scope, (ScriptObject)wrappedExpr);
@@ -490,20 +520,6 @@ public final class ScriptRuntime {
}
/**
- * Exiting a {@code with} node requires restoring scope. This is the implementation
- *
- * @param scope existing scope
- *
- * @return restored scope
- */
- public static ScriptObject closeWith(final ScriptObject scope) {
- if (scope instanceof WithObject) {
- return ((WithObject)scope).getParentScope();
- }
- return scope;
- }
-
- /**
* ECMA 11.6.1 - The addition operator (+) - generic implementation
* Compiler specializes using {@link jdk.nashorn.internal.codegen.RuntimeCallSite}
* if any type information is available for any of the operands
@@ -525,7 +541,7 @@ public final class ScriptRuntime {
final boolean xIsUndefined = x == UNDEFINED;
final boolean yIsUndefined = y == UNDEFINED;
- if ((xIsNumber && yIsUndefined) || (xIsUndefined && yIsNumber) || (xIsUndefined && yIsUndefined)) {
+ if (xIsNumber && yIsUndefined || xIsUndefined && yIsNumber || xIsUndefined && yIsUndefined) {
return Double.NaN;
}
@@ -535,7 +551,11 @@ public final class ScriptRuntime {
if (xPrim instanceof String || yPrim instanceof String
|| xPrim instanceof ConsString || yPrim instanceof ConsString) {
- return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
+ try {
+ return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "concat.string.too.big");
+ }
}
return JSType.toNumber(xPrim) + JSType.toNumber(yPrim);
@@ -577,6 +597,13 @@ public final class ScriptRuntime {
if (property != null) {
if (obj instanceof ScriptObject) {
obj = ((ScriptObject)obj).get(property);
+ if(Global.isLocationPropertyPlaceholder(obj)) {
+ if(CompilerConstants.__LINE__.name().equals(property)) {
+ obj = Integer.valueOf(0);
+ } else {
+ obj = "";
+ }
+ }
} else if (object instanceof Undefined) {
obj = ((Undefined)obj).get(property);
} else if (object == null) {
@@ -689,67 +716,100 @@ public final class ScriptRuntime {
/** ECMA 11.9.3 The Abstract Equality Comparison Algorithm */
private static boolean equals(final Object x, final Object y) {
- final JSType xType = JSType.of(x);
- final JSType yType = JSType.of(y);
+ if (x == y) {
+ return true;
+ }
+ if (x instanceof ScriptObject && y instanceof ScriptObject) {
+ return x == y;
+ }
+ if (x instanceof ScriptObjectMirror || y instanceof ScriptObjectMirror) {
+ return ScriptObjectMirror.identical(x, y);
+ }
+ return equalValues(x, y);
+ }
- if (xType == yType) {
+ /**
+ * Extracted portion of {@code equals()} that compares objects by value (or by reference, if no known value
+ * comparison applies).
+ * @param x one value
+ * @param y another value
+ * @return true if they're equal according to 11.9.3
+ */
+ private static boolean equalValues(final Object x, final Object y) {
+ final JSType xType = JSType.ofNoFunction(x);
+ final JSType yType = JSType.ofNoFunction(y);
- if (xType == JSType.UNDEFINED || xType == JSType.NULL) {
- return true;
- }
+ if (xType == yType) {
+ return equalSameTypeValues(x, y, xType);
+ }
- if (xType == JSType.NUMBER) {
- final double xVal = ((Number)x).doubleValue();
- final double yVal = ((Number)y).doubleValue();
- if (Double.isNaN(xVal) || Double.isNaN(yVal)) {
- return false;
- }
+ return equalDifferentTypeValues(x, y, xType, yType);
+ }
- return xVal == yVal;
- }
+ /**
+ * Extracted portion of {@link #equals(Object, Object)} and {@link #strictEquals(Object, Object)} that compares
+ * values belonging to the same JSType.
+ * @param x one value
+ * @param y another value
+ * @param type the common type for the values
+ * @return true if they're equal
+ */
+ private static boolean equalSameTypeValues(final Object x, final Object y, final JSType type) {
+ if (type == JSType.UNDEFINED || type == JSType.NULL) {
+ return true;
+ }
- if (xType == JSType.STRING) {
- // String may be represented by ConsString
- return x.toString().equals(y.toString());
- }
+ if (type == JSType.NUMBER) {
+ return ((Number)x).doubleValue() == ((Number)y).doubleValue();
+ }
- if (xType == JSType.BOOLEAN) {
- // Boolean comparison
- return x.equals(y);
- }
+ if (type == JSType.STRING) {
+ // String may be represented by ConsString
+ return x.toString().equals(y.toString());
+ }
- return x == y;
+ if (type == JSType.BOOLEAN) {
+ return ((Boolean)x).booleanValue() == ((Boolean)y).booleanValue();
}
- if ((xType == JSType.UNDEFINED && yType == JSType.NULL) ||
- (xType == JSType.NULL && yType == JSType.UNDEFINED)) {
+ return x == y;
+ }
+
+ /**
+ * Extracted portion of {@link #equals(Object, Object)} that compares values belonging to different JSTypes.
+ * @param x one value
+ * @param y another value
+ * @param xType the type for the value x
+ * @param yType the type for the value y
+ * @return true if they're equal
+ */
+ private static boolean equalDifferentTypeValues(final Object x, final Object y, final JSType xType, final JSType yType) {
+ if (xType == JSType.UNDEFINED && yType == JSType.NULL || xType == JSType.NULL && yType == JSType.UNDEFINED) {
return true;
}
if (xType == JSType.NUMBER && yType == JSType.STRING) {
- return EQ(x, JSType.toNumber(y));
+ return equals(x, JSType.toNumber(y));
}
if (xType == JSType.STRING && yType == JSType.NUMBER) {
- return EQ(JSType.toNumber(x), y);
+ return equals(JSType.toNumber(x), y);
}
if (xType == JSType.BOOLEAN) {
- return EQ(JSType.toNumber(x), y);
+ return equals(JSType.toNumber(x), y);
}
if (yType == JSType.BOOLEAN) {
- return EQ(x, JSType.toNumber(y));
+ return equals(x, JSType.toNumber(y));
}
- if ((xType == JSType.STRING || xType == JSType.NUMBER) &&
- (y instanceof ScriptObject)) {
- return EQ(x, JSType.toPrimitive(y));
+ if ((xType == JSType.STRING || xType == JSType.NUMBER) && y instanceof ScriptObject) {
+ return equals(x, JSType.toPrimitive(y));
}
- if ((x instanceof ScriptObject) &&
- (yType == JSType.STRING || yType == JSType.NUMBER)) {
- return EQ(JSType.toPrimitive(x), y);
+ if (x instanceof ScriptObject && (yType == JSType.STRING || yType == JSType.NUMBER)) {
+ return equals(JSType.toPrimitive(x), y);
}
return false;
@@ -781,39 +841,17 @@ public final class ScriptRuntime {
/** ECMA 11.9.6 The Strict Equality Comparison Algorithm */
private static boolean strictEquals(final Object x, final Object y) {
- final JSType xType = JSType.of(x);
- final JSType yType = JSType.of(y);
+ // NOTE: you might be tempted to do a quick x == y comparison. Remember, though, that any Double object having
+ // NaN value is not equal to itself by value even though it is referentially.
+
+ final JSType xType = JSType.ofNoFunction(x);
+ final JSType yType = JSType.ofNoFunction(y);
if (xType != yType) {
return false;
}
- if (xType == JSType.UNDEFINED || xType == JSType.NULL) {
- return true;
- }
-
- if (xType == JSType.NUMBER) {
- final double xVal = ((Number)x).doubleValue();
- final double yVal = ((Number)y).doubleValue();
-
- if (Double.isNaN(xVal) || Double.isNaN(yVal)) {
- return false;
- }
-
- return xVal == yVal;
- }
-
- if (xType == JSType.STRING) {
- // String may be represented by ConsString
- return x.toString().equals(y.toString());
- }
-
- if (xType == JSType.BOOLEAN) {
- return x.equals(y);
- }
-
- // finally, the object identity comparison
- return x == y;
+ return equalSameTypeValues(x, y, xType);
}
/**
@@ -825,9 +863,9 @@ public final class ScriptRuntime {
* @return true if objects are equal
*/
public static boolean IN(final Object property, final Object obj) {
- final JSType rvalType = JSType.of(obj);
+ final JSType rvalType = JSType.ofNoFunction(obj);
- if (rvalType == JSType.OBJECT || rvalType == JSType.FUNCTION) {
+ if (rvalType == JSType.OBJECT) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).has(property);
}
@@ -884,7 +922,7 @@ public final class ScriptRuntime {
*/
public static boolean LT(final Object x, final Object y) {
final Object value = lessThan(x, y, true);
- return (value == UNDEFINED) ? false : (Boolean)value;
+ return value == UNDEFINED ? false : (Boolean)value;
}
/**
@@ -897,7 +935,7 @@ public final class ScriptRuntime {
*/
public static boolean GT(final Object x, final Object y) {
final Object value = lessThan(y, x, false);
- return (value == UNDEFINED) ? false : (Boolean)value;
+ return value == UNDEFINED ? false : (Boolean)value;
}
/**
@@ -910,7 +948,7 @@ public final class ScriptRuntime {
*/
public static boolean LE(final Object x, final Object y) {
final Object value = lessThan(y, x, false);
- return (!(Boolean.TRUE.equals(value) || value == UNDEFINED));
+ return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
}
/**
@@ -923,7 +961,7 @@ public final class ScriptRuntime {
*/
public static boolean GE(final Object x, final Object y) {
final Object value = lessThan(x, y, true);
- return (!(Boolean.TRUE.equals(value) || value == UNDEFINED));
+ return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
}
/** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */
@@ -939,9 +977,9 @@ public final class ScriptRuntime {
px = JSType.toPrimitive(x, Number.class);
}
- if (JSType.of(px) == JSType.STRING && JSType.of(py) == JSType.STRING) {
+ if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) {
// May be String or ConsString
- return (px.toString()).compareTo(py.toString()) < 0;
+ return px.toString().compareTo(py.toString()) < 0;
}
final double nx = JSType.toNumber(px);
@@ -966,4 +1004,19 @@ public final class ScriptRuntime {
return nx < ny;
}
+ /**
+ * Tag a reserved name as invalidated - used when someone writes
+ * to a property with this name - overly conservative, but link time
+ * is too late to apply e.g. apply-&gt;call specialization
+ * @param name property name
+ */
+ public static void invalidateReservedBuiltinName(final String name) {
+ final Context context = Context.getContextTrusted();
+ final SwitchPoint sp = context.getBuiltinSwitchPoint(name);
+ assert sp != null;
+ if (sp != null) {
+ context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+ SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+ }
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
index 8a03533e..83583232 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.io.BufferedReader;
import java.io.File;
@@ -107,8 +107,8 @@ public final class ScriptingFunctions {
if (file instanceof File) {
f = (File)file;
- } else if (file instanceof String) {
- f = new java.io.File((String)file);
+ } else if (file instanceof String || file instanceof ConsString) {
+ f = new java.io.File(((CharSequence)file).toString());
}
if (f == null || !f.isFile()) {
@@ -157,7 +157,7 @@ public final class ScriptingFunctions {
// Set up ENV variables.
final Map<String, String> environment = processBuilder.environment();
environment.clear();
- for (Map.Entry<Object, Object> entry : envProperties.entrySet()) {
+ for (final Map.Entry<Object, Object> entry : envProperties.entrySet()) {
environment.put(JSType.toString(entry.getKey()), JSType.toString(entry.getValue()));
}
}
@@ -168,15 +168,15 @@ public final class ScriptingFunctions {
// Collect output.
final StringBuilder outBuffer = new StringBuilder();
- Thread outThread = new Thread(new Runnable() {
+ final Thread outThread = new Thread(new Runnable() {
@Override
public void run() {
- char buffer[] = new char[1024];
+ final char buffer[] = new char[1024];
try (final InputStreamReader inputStream = new InputStreamReader(process.getInputStream())) {
for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) {
outBuffer.append(buffer, 0, length);
}
- } catch (IOException ex) {
+ } catch (final IOException ex) {
exception[0] = ex;
}
}
@@ -184,15 +184,15 @@ public final class ScriptingFunctions {
// Collect errors.
final StringBuilder errBuffer = new StringBuilder();
- Thread errThread = new Thread(new Runnable() {
+ final Thread errThread = new Thread(new Runnable() {
@Override
public void run() {
- char buffer[] = new char[1024];
+ final char buffer[] = new char[1024];
try (final InputStreamReader inputStream = new InputStreamReader(process.getErrorStream())) {
for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) {
errBuffer.append(buffer, 0, length);
}
- } catch (IOException ex) {
+ } catch (final IOException ex) {
exception[1] = ex;
}
}
@@ -205,10 +205,10 @@ public final class ScriptingFunctions {
// If input is present, pass on to process.
try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) {
if (input != UNDEFINED) {
- String in = JSType.toString(input);
+ final String in = JSType.toString(input);
outputStream.write(in, 0, in.length());
}
- } catch (IOException ex) {
+ } catch (final IOException ex) {
// Process was not expecting input. May be normal state of affairs.
}
@@ -221,14 +221,14 @@ public final class ScriptingFunctions {
final String err = errBuffer.toString();
// Set globals for secondary results.
- global.set(OUT_NAME, out, false);
- global.set(ERR_NAME, err, false);
- global.set(EXIT_NAME, exit, false);
+ global.set(OUT_NAME, out, 0);
+ global.set(ERR_NAME, err, 0);
+ global.set(EXIT_NAME, exit, 0);
// Propagate exception if present.
- for (int i = 0; i < exception.length; i++) {
- if (exception[i] != null) {
- throw exception[i];
+ for (final IOException element : exception) {
+ if (element != null) {
+ throw element;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
index edee3748..90bbf43c 100644
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@@ -25,17 +25,17 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.lookup.Lookup.MH;
-
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.SwitchPoint;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.lookup.Lookup;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
-
/**
* Instances of this class are quite ephemeral; they only exist for the duration of an invocation of
* {@link ScriptObject#findSetMethod(CallSiteDescriptor, jdk.internal.dynalink.linker.LinkRequest)} and
@@ -43,10 +43,12 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
*/
final class SetMethodCreator {
// See constructor parameters for description of fields
- private final ScriptObject sobj;
- private final PropertyMap map;
- private final FindProperty find;
+ private final ScriptObject sobj;
+ private final PropertyMap map;
+ private final FindProperty find;
private final CallSiteDescriptor desc;
+ private final Class<?> type;
+ private final LinkRequest request;
/**
* Creates a new property setter method creator.
@@ -54,12 +56,16 @@ final class SetMethodCreator {
* @param find a result of a {@link ScriptObject#findProperty(String, boolean)} on the object for the property we
* want to create a setter for. Can be null if the property does not yet exist on the object.
* @param desc the descriptor of the call site that triggered the property setter lookup
+ * @param request the link request
*/
- SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc) {
- this.sobj = sobj;
- this.map = sobj.getMap();
- this.find = find;
- this.desc = desc;
+ SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final LinkRequest request) {
+ this.sobj = sobj;
+ this.map = sobj.getMap();
+ this.find = find;
+ this.desc = desc;
+ this.type = desc.getMethodType().parameterType(1);
+ this.request = request;
+
}
private String getName() {
@@ -74,8 +80,8 @@ final class SetMethodCreator {
* Creates the actual guarded invocation that represents the dynamic setter method for the property.
* @return the actual guarded invocation that represents the dynamic setter method for the property.
*/
- GuardedInvocation createGuardedInvocation() {
- return createSetMethod().createGuardedInvocation();
+ GuardedInvocation createGuardedInvocation(final SwitchPoint builtinSwitchPoint) {
+ return createSetMethod(builtinSwitchPoint).createGuardedInvocation();
}
/**
@@ -95,7 +101,7 @@ final class SetMethodCreator {
SetMethod(final MethodHandle methodHandle, final Property property) {
assert methodHandle != null;
this.methodHandle = methodHandle;
- this.property = property;
+ this.property = property;
}
/**
@@ -103,12 +109,16 @@ final class SetMethodCreator {
* @return the composed guarded invocation that represents the dynamic setter method for the property.
*/
GuardedInvocation createGuardedInvocation() {
- return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc));
+ // getGuard() and getException() either both return null, or neither does. The reason for that is that now
+ // getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
+ // relink on ClassCastException.
+ final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request);
+ return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
+ (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
-
}
- private SetMethod createSetMethod() {
+ private SetMethod createSetMethod(final SwitchPoint builtinSwitchPoint) {
if (find != null) {
return createExistingPropertySetter();
}
@@ -119,7 +129,7 @@ final class SetMethodCreator {
return createGlobalPropertySetter();
}
- return createNewPropertySetter();
+ return createNewPropertySetter(builtinSwitchPoint);
}
private void checkStrictCreateNewVariable() {
@@ -132,14 +142,36 @@ final class SetMethodCreator {
private SetMethod createExistingPropertySetter() {
final Property property = find.getProperty();
- final Class<?> type = desc.getMethodType().parameterType(1);
- final MethodHandle methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc));
+ final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
+ final MethodHandle methodHandle;
+
+ if (NashornCallSiteDescriptor.isDeclaration(desc)) {
+ assert property.needsDeclaration();
+ // This is a LET or CONST being declared. The property is already there but flagged as needing declaration.
+ // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set
+ // method if the pre-callsite map is stable (which should be the case for function scopes except for
+ // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates
+ // a new PropertyMap on the fly.
+ final PropertyMap oldMap = getMap();
+ final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION);
+ final PropertyMap newMap = oldMap.replaceProperty(property, newProperty);
+ final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request);
+ final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type());
+
+ // cas map used as guard, if true that means we can do the set fast
+ MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
+ casMap = MH.dropArguments(casMap, 1, type);
+ casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
+ methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter);
+ } else {
+ methodHandle = find.getSetter(type, isStrict, request);
+ }
assert methodHandle != null;
assert property != null;
final MethodHandle boundHandle;
- if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) {
+ if (!(property instanceof UserAccessorProperty) && find.isInherited()) {
boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
} else {
boundHandle = methodHandle;
@@ -149,11 +181,11 @@ final class SetMethodCreator {
private SetMethod createGlobalPropertySetter() {
final ScriptObject global = Context.getGlobal();
- return new SetMethod(MH.filterArguments(global.addSpill(getName()), 0, ScriptObject.GLOBALFILTER), null);
+ return new SetMethod(MH.filterArguments(global.addSpill(type, getName()), 0, ScriptObject.GLOBALFILTER), null);
}
- private SetMethod createNewPropertySetter() {
- final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
+ private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) {
+ final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint);
final PropertyListeners listeners = map.getListeners();
if (listeners != null) {
listeners.propertyAdded(sm.property);
@@ -161,38 +193,53 @@ final class SetMethodCreator {
return sm;
}
- private SetMethod createNewFieldSetter() {
- final PropertyMap oldMap = getMap();
- final Property property = new AccessorProperty(getName(), 0, sobj.getClass(), oldMap.getFieldCount());
- final PropertyMap newMap = oldMap.addProperty(property);
- MethodHandle setter = MH.insertArguments(ScriptObject.SETFIELD, 0, desc, oldMap, newMap, property.getSetter(Object.class, newMap));
+ private SetMethod createNewSetter(final Property property, final SwitchPoint builtinSwitchPoint) {
+ property.setBuiltinSwitchPoint(builtinSwitchPoint);
- return new SetMethod(MH.asType(setter, Lookup.SET_OBJECT_TYPE), property);
- }
+ final PropertyMap oldMap = getMap();
+ final PropertyMap newMap = getNewMap(property);
+ final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- private SetMethod createNewSpillPropertySetter() {
- final int nextSpill = getMap().getSpillLength();
+ //fast type specific setter
+ final MethodHandle fastSetter = property.getSetter(type, newMap); //0 sobj, 1 value, slot folded for spill property already
- final Property property = new AccessorProperty(getName(), Property.IS_SPILL, nextSpill);
- return new SetMethod(createSpillMethodHandle(nextSpill, property), property);
+ //slow setter, that calls ScriptObject.set with appropraite type and key name
+ MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
+ slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
+ slowSetter = MH.insertArguments(slowSetter, 1, name);
+ slowSetter = MH.asType(slowSetter, slowSetter.type().changeParameterType(0, Object.class));
+
+ assert slowSetter.type().equals(fastSetter.type()) : "slow=" + slowSetter + " != fast=" + fastSetter;
+
+ //cas map used as guard, if true that means we can do the set fast
+ MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
+ casMap = MH.dropArguments(casMap, 1, type);
+ casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
+ final MethodHandle casGuard = MH.guardWithTest(casMap, fastSetter, slowSetter);
+
+ //outermost level needs an extendable check. if object can be extended, guard is true and
+ //we can run the cas setter. The setter goes to "nop" VOID_RETURN if false or throws an
+ //exception if we are in strict mode and object is not extensible
+ MethodHandle extCheck = MH.insertArguments(ScriptObject.EXTENSION_CHECK, 1, isStrict, name);
+ extCheck = MH.asType(extCheck, extCheck.type().changeParameterType(0, Object.class));
+ extCheck = MH.dropArguments(extCheck, 1, type);
+
+ MethodHandle nop = JSType.VOID_RETURN.methodHandle();
+ nop = MH.dropArguments(nop, 0, Object.class, type);
+
+ return new SetMethod(MH.asType(MH.guardWithTest(extCheck, casGuard, nop), fastSetter.type()), property);
}
- private MethodHandle createSpillMethodHandle(final int nextSpill, Property property) {
- final PropertyMap oldMap = getMap();
- final PropertyMap newMap = getNewMap(property);
+ private SetMethod createNewFieldSetter(final SwitchPoint builtinSwitchPoint) {
+ return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type), builtinSwitchPoint);
+ }
- final Object[] spill = sobj.spill;
- if (spill == null) {
- return MH.insertArguments(ScriptObject.SETSPILLWITHNEW, 0, desc, oldMap, newMap, nextSpill);
- } else if (nextSpill < spill.length) {
- return MH.insertArguments(ScriptObject.SETSPILL, 0, desc, oldMap, newMap, nextSpill);
- } else {
- final int newLength = (nextSpill + ScriptObject.SPILL_RATE) / ScriptObject.SPILL_RATE * ScriptObject.SPILL_RATE;
- return MH.insertArguments(ScriptObject.SETSPILLWITHGROW, 0, desc, oldMap, newMap, nextSpill, newLength);
- }
+ private SetMethod createNewSpillPropertySetter(final SwitchPoint builtinSwitchPoint) {
+ return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type), builtinSwitchPoint);
}
- private PropertyMap getNewMap(Property property) {
+ private PropertyMap getNewMap(final Property property) {
return getMap().addProperty(property);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/Source.java b/src/jdk/nashorn/internal/runtime/Source.java
index 1423c163..38d4b85a 100644
--- a/src/jdk/nashorn/internal/runtime/Source.java
+++ b/src/jdk/nashorn/internal/runtime/Source.java
@@ -45,20 +45,25 @@ import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Objects;
import java.util.WeakHashMap;
import jdk.nashorn.api.scripting.URLReader;
import jdk.nashorn.internal.parser.Token;
-
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Source objects track the origin of JavaScript entities.
*/
-public final class Source {
-
- private static final DebugLogger DEBUG = new DebugLogger("source");
+@Logger(name="source")
+public final class Source implements Loggable {
private static final int BUF_SIZE = 8 * 1024;
private static final Cache CACHE = new Cache();
+ // Message digest to file name encoder
+ private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+
/**
* Descriptive name of the source as supplied by the user. Used for error
* reporting to the user. For example, SyntaxError will use this to print message.
@@ -79,8 +84,11 @@ public final class Source {
/** Cached hash code */
private int hash;
- /** Message digest */
- private byte[] digest;
+ /** Base64-encoded SHA1 digest of this source object */
+ private volatile byte[] digest;
+
+ /** source URL set via //@ sourceURL or //# sourceURL directive */
+ private String explicitURL;
// Do *not* make this public, ever! Trusts the URL and content.
private Source(final String name, final String base, final Data data) {
@@ -97,13 +105,14 @@ public final class Source {
// Force any access errors
data.checkPermissionAndClose();
return existingSource;
- } else {
- // All sources in cache must be fully loaded
- data.load();
- CACHE.put(newSource, newSource);
- return newSource;
}
- } catch (RuntimeException e) {
+
+ // All sources in cache must be fully loaded
+ data.load();
+ CACHE.put(newSource, newSource);
+
+ return newSource;
+ } catch (final RuntimeException e) {
final Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
@@ -139,40 +148,46 @@ public final class Source {
long lastModified();
char[] array();
+
+ boolean isEvalCode();
}
private static class RawData implements Data {
private final char[] array;
+ private final boolean evalCode;
private int hash;
- private RawData(final char[] array) {
+ private RawData(final char[] array, final boolean evalCode) {
this.array = Objects.requireNonNull(array);
+ this.evalCode = evalCode;
}
- private RawData(final String source) {
+ private RawData(final String source, final boolean evalCode) {
this.array = Objects.requireNonNull(source).toCharArray();
+ this.evalCode = evalCode;
}
private RawData(final Reader reader) throws IOException {
- this(readFully(reader));
+ this(readFully(reader), false);
}
@Override
public int hashCode() {
int h = hash;
if (h == 0) {
- h = hash = Arrays.hashCode(array);
+ h = hash = Arrays.hashCode(array) ^ (evalCode? 1 : 0);
}
return h;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof RawData) {
- return Arrays.equals(array, ((RawData)obj).array);
+ final RawData other = (RawData)obj;
+ return Arrays.equals(array, other.array) && evalCode == other.evalCode;
}
return false;
}
@@ -203,6 +218,10 @@ public final class Source {
}
+ @Override
+ public boolean isEvalCode() {
+ return evalCode;
+ }
}
private static class URLData implements Data {
@@ -228,7 +247,7 @@ public final class Source {
}
@Override
- public boolean equals(Object other) {
+ public boolean equals(final Object other) {
if (this == other) {
return true;
}
@@ -236,7 +255,7 @@ public final class Source {
return false;
}
- URLData otherData = (URLData) other;
+ final URLData otherData = (URLData) other;
if (url.equals(otherData.url)) {
// Make sure both have meta data loaded
@@ -248,7 +267,7 @@ public final class Source {
} else if (otherData.isDeferred()) {
otherData.loadMeta();
}
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
}
@@ -284,12 +303,20 @@ public final class Source {
return array;
}
+ @Override
+ public boolean isEvalCode() {
+ return false;
+ }
+
boolean isDeferred() {
return array == null;
}
+ @SuppressWarnings("try")
protected void checkPermissionAndClose() throws IOException {
- try (InputStream in = url.openStream()) {}
+ try (InputStream in = url.openStream()) {
+ // empty
+ }
debug("permission checked for ", url);
}
@@ -353,7 +380,10 @@ public final class Source {
}
private static void debug(final Object... msg) {
- DEBUG.info(msg);
+ final DebugLogger logger = getLoggerStatic();
+ if (logger != null) {
+ logger.info(msg);
+ }
}
private char[] data() {
@@ -361,23 +391,50 @@ public final class Source {
}
/**
- * Returns an instance
+ * Returns a Source instance
*
* @param name source name
* @param content contents as char array
+ * @param isEval does this represent code from 'eval' call?
+ * @return source instance
+ */
+ public static Source sourceFor(final String name, final char[] content, final boolean isEval) {
+ return new Source(name, baseName(name), new RawData(content, isEval));
+ }
+
+ /**
+ * Returns a Source instance
+ *
+ * @param name source name
+ * @param content contents as char array
+ *
+ * @return source instance
*/
public static Source sourceFor(final String name, final char[] content) {
- return new Source(name, baseName(name), new RawData(content));
+ return sourceFor(name, content, false);
}
/**
- * Returns an instance
+ * Returns a Source instance
*
* @param name source name
* @param content contents as string
+ * @param isEval does this represent code from 'eval' call?
+ * @return source instance
+ */
+ public static Source sourceFor(final String name, final String content, final boolean isEval) {
+ return new Source(name, baseName(name), new RawData(content, isEval));
+ }
+
+ /**
+ * Returns a Source instance
+ *
+ * @param name source name
+ * @param content contents as string
+ * @return source instance
*/
public static Source sourceFor(final String name, final String content) {
- return new Source(name, baseName(name), new RawData(content));
+ return sourceFor(name, content, false);
}
/**
@@ -386,6 +443,8 @@ public final class Source {
* @param name source name
* @param url url from which source can be loaded
*
+ * @return source instance
+ *
* @throws IOException if source cannot be loaded
*/
public static Source sourceFor(final String name, final URL url) throws IOException {
@@ -399,6 +458,8 @@ public final class Source {
* @param url url from which source can be loaded
* @param cs Charset used to convert bytes to chars
*
+ * @return source instance
+ *
* @throws IOException if source cannot be loaded
*/
public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException {
@@ -411,6 +472,8 @@ public final class Source {
* @param name source name
* @param file file from which source can be loaded
*
+ * @return source instance
+ *
* @throws IOException if source cannot be loaded
*/
public static Source sourceFor(final String name, final File file) throws IOException {
@@ -424,6 +487,8 @@ public final class Source {
* @param file file from which source can be loaded
* @param cs Charset used to convert bytes to chars
*
+ * @return source instance
+ *
* @throws IOException if source cannot be loaded
*/
public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException {
@@ -436,6 +501,9 @@ public final class Source {
*
* @param name source name
* @param reader reader from which source can be loaded
+ *
+ * @return source instance
+ *
* @throws IOException if source cannot be loaded
*/
public static Source sourceFor(final String name, final Reader reader) throws IOException {
@@ -532,14 +600,39 @@ public final class Source {
}
/**
+ * Get explicit source URL.
+ * @return URL set vial sourceURL directive
+ */
+ public String getExplicitURL() {
+ return explicitURL;
+ }
+
+ /**
+ * Set explicit source URL.
+ * @param explicitURL URL set via sourceURL directive
+ */
+ public void setExplicitURL(final String explicitURL) {
+ this.explicitURL = explicitURL;
+ }
+
+ /**
+ * Returns whether this source was submitted via 'eval' call or not.
+ *
+ * @return true if this source represents code submitted via 'eval'
+ */
+ public boolean isEvalCode() {
+ return data.isEvalCode();
+ }
+
+ /**
* Find the beginning of the line containing position.
* @param position Index to offending token.
* @return Index of first character of line.
*/
private int findBOLN(final int position) {
- final char[] data = data();
+ final char[] d = data();
for (int i = position - 1; i > 0; i--) {
- final char ch = data[i];
+ final char ch = d[i];
if (ch == '\n' || ch == '\r') {
return i + 1;
@@ -555,10 +648,10 @@ public final class Source {
* @return Index of last character of line.
*/
private int findEOLN(final int position) {
- final char[] data = data();
- final int length = data.length;
+ final char[] d = data();
+ final int length = d.length;
for (int i = position; i < length; i++) {
- final char ch = data[i];
+ final char ch = d[i];
if (ch == '\n' || ch == '\r') {
return i - 1;
@@ -578,12 +671,12 @@ public final class Source {
* @return Line number.
*/
public int getLine(final int position) {
- final char[] data = data();
+ final char[] d = data();
// Line count starts at 1.
int line = 1;
for (int i = 0; i < position; i++) {
- final char ch = data[i];
+ final char ch = d[i];
// Works for both \n and \r\n.
if (ch == '\n') {
line++;
@@ -618,11 +711,16 @@ public final class Source {
}
/**
- * Get the content of this source as a char array
- * @return content
+ * Get the content of this source as a char array. Note that the underlying array is returned instead of a
+ * clone; modifying the char array will cause modification to the source; this should not be done. While
+ * there is an apparent danger that we allow unfettered access to an underlying mutable array, the
+ * {@code Source} class is in a restricted {@code jdk.nashorn.internal.*} package and as such it is
+ * inaccessible by external actors in an environment with a security manager. Returning a clone would be
+ * detrimental to performance.
+ * @return content the content of this source as a char array
*/
public char[] getContent() {
- return data().clone();
+ return data();
}
/**
@@ -711,12 +809,17 @@ public final class Source {
}
/**
- * Get a message digest for this source.
+ * Get a Base64-encoded SHA1 digest for this source.
*
- * @return a message digest for this source
+ * @return a Base64-encoded SHA1 digest for this source
*/
- public synchronized byte[] getDigest() {
- if (digest == null) {
+ public String getDigest() {
+ return new String(getDigestBytes(), StandardCharsets.US_ASCII);
+ }
+
+ private byte[] getDigestBytes() {
+ byte[] ldigest = digest;
+ if (ldigest == null) {
final char[] content = data();
final byte[] bytes = new byte[content.length * 2];
@@ -736,12 +839,12 @@ public final class Source {
if (getURL() != null) {
md.update(getURL().toString().getBytes(StandardCharsets.UTF_8));
}
- digest = md.digest(bytes);
- } catch (NoSuchAlgorithmException e) {
+ digest = ldigest = BASE64.encode(md.digest(bytes));
+ } catch (final NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
- return digest;
+ return ldigest;
}
/**
@@ -847,4 +950,19 @@ public final class Source {
return null;
}
}
+
+ private static DebugLogger getLoggerStatic() {
+ final Context context = Context.getContextTrustedOrNull();
+ return context == null ? null : context.getLogger(Source.class);
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return initLogger(Context.getContextTrusted());
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/Specialization.java b/src/jdk/nashorn/internal/runtime/Specialization.java
new file mode 100644
index 00000000..9807cc61
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/Specialization.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.lang.invoke.MethodHandle;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
+
+/**
+ * Specialization info for a {@link SpecializedFunction}
+ */
+public final class Specialization {
+ private final MethodHandle mh;
+ private final Class<? extends LinkLogic> linkLogicClass;
+ private final boolean isOptimistic;
+
+ /**
+ * Constructor
+ *
+ * @param mh invoker method handler
+ */
+ public Specialization(final MethodHandle mh) {
+ this(mh, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param mh invoker method handler
+ * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException}
+ * which would have to lead to a relink and return value processing
+ */
+ public Specialization(final MethodHandle mh, final boolean isOptimistic) {
+ this(mh, null, isOptimistic);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param mh invoker method handler
+ * @param linkLogicClass extra link logic needed for this function. Instances of this class also contains logic for checking
+ * if this can be linked on its first encounter, which is needed as per our standard linker semantics
+ * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException}
+ * which would have to lead to a relink and return value processing
+ */
+ public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> linkLogicClass, final boolean isOptimistic) {
+ this.mh = mh;
+ this.isOptimistic = isOptimistic;
+ if (linkLogicClass != null) {
+ //null out the "empty" link logic class for optimization purposes
+ //we only use the empty instance because we can't default class annotations
+ //to null
+ this.linkLogicClass = LinkLogic.isEmpty(linkLogicClass) ? null : linkLogicClass;
+ } else {
+ this.linkLogicClass = null;
+ }
+ }
+
+ /**
+ * Get the method handle for the invoker of this ScriptFunction
+ * @return the method handle
+ */
+ public MethodHandle getMethodHandle() {
+ return mh;
+ }
+
+ /**
+ * Get the link logic class for this ScriptFunction
+ * @return link logic class info, i.e. one whose instance contains stuff like
+ * "do we need exception check for every call", and logic to check if we may link
+ */
+ public Class<? extends LinkLogic> getLinkLogicClass() {
+ return linkLogicClass;
+ }
+
+ /**
+ * An optimistic specialization is one that can throw UnwarrantedOptimismException.
+ * This is allowed for native methods, as long as they are functional, i.e. don't change
+ * any state between entering and throwing the UOE. Then we can re-execute a wider version
+ * of the method in the continuation. Rest-of method generation for optimistic builtins is
+ * of course not possible, but this approach works and fits into the same relinking
+ * framework
+ *
+ * @return true if optimistic
+ */
+ public boolean isOptimistic() {
+ return isOptimistic;
+ }
+
+}
+
diff --git a/src/jdk/nashorn/internal/runtime/SpillProperty.java b/src/jdk/nashorn/internal/runtime/SpillProperty.java
new file mode 100644
index 00000000..7b42b2bf
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2010-2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+/**
+ * Spill property
+ */
+public class SpillProperty extends AccessorProperty {
+ private static final long serialVersionUID = 3028496245198669460L;
+
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ private static final MethodHandle PARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "primitiveSpill", long[].class), MH.type(long[].class, Object.class));
+ private static final MethodHandle OARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "objectSpill", Object[].class), MH.type(Object[].class, Object.class));
+
+ private static final MethodHandle OBJECT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, OARRAY_GETTER);
+ private static final MethodHandle PRIMITIVE_GETTER = MH.filterArguments(MH.arrayElementGetter(long[].class), 0, PARRAY_GETTER);
+ private static final MethodHandle OBJECT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, OARRAY_GETTER);
+ private static final MethodHandle PRIMITIVE_SETTER = MH.filterArguments(MH.arrayElementSetter(long[].class), 0, PARRAY_GETTER);
+
+ private static class Accessors {
+ private MethodHandle objectGetter;
+ private MethodHandle objectSetter;
+ private MethodHandle primitiveGetter;
+ private MethodHandle primitiveSetter;
+
+ private final int slot;
+ private final MethodHandle ensureSpillSize;
+
+ private static Accessors ACCESSOR_CACHE[] = new Accessors[512];
+
+ //private static final Map<Integer, Reference<Accessors>> ACCESSOR_CACHE = Collections.synchronizedMap(new WeakHashMap<Integer, Reference<Accessors>>());
+
+ Accessors(final int slot) {
+ assert slot >= 0;
+ this.slot = slot;
+ this.ensureSpillSize = MH.asType(MH.insertArguments(ScriptObject.ENSURE_SPILL_SIZE, 1, slot), MH.type(Object.class, Object.class));
+ }
+
+ private static void ensure(final int slot) {
+ int len = ACCESSOR_CACHE.length;
+ if (slot >= len) {
+ do {
+ len *= 2;
+ } while (slot >= len);
+ final Accessors newCache[] = new Accessors[len];
+ System.arraycopy(ACCESSOR_CACHE, 0, newCache, 0, ACCESSOR_CACHE.length);
+ ACCESSOR_CACHE = newCache;
+ }
+ }
+
+ static MethodHandle getCached(final int slot, final boolean isPrimitive, final boolean isGetter) {
+ //Reference<Accessors> ref = ACCESSOR_CACHE.get(slot);
+ ensure(slot);
+ Accessors acc = ACCESSOR_CACHE[slot];
+ if (acc == null) {
+ acc = new Accessors(slot);
+ ACCESSOR_CACHE[slot] = acc;
+ }
+
+ return acc.getOrCreate(isPrimitive, isGetter);
+ }
+
+ private static MethodHandle primordial(final boolean isPrimitive, final boolean isGetter) {
+ if (isPrimitive) {
+ return isGetter ? PRIMITIVE_GETTER : PRIMITIVE_SETTER;
+ }
+ return isGetter ? OBJECT_GETTER : OBJECT_SETTER;
+ }
+
+ MethodHandle getOrCreate(final boolean isPrimitive, final boolean isGetter) {
+ MethodHandle accessor;
+
+ accessor = getInner(isPrimitive, isGetter);
+ if (accessor != null) {
+ return accessor;
+ }
+
+ accessor = primordial(isPrimitive, isGetter);
+ accessor = MH.insertArguments(accessor, 1, slot);
+ if (!isGetter) {
+ accessor = MH.filterArguments(accessor, 0, ensureSpillSize);
+ }
+ setInner(isPrimitive, isGetter, accessor);
+
+ return accessor;
+ }
+
+ void setInner(final boolean isPrimitive, final boolean isGetter, final MethodHandle mh) {
+ if (isPrimitive) {
+ if (isGetter) {
+ primitiveGetter = mh;
+ } else {
+ primitiveSetter = mh;
+ }
+ } else {
+ if (isGetter) {
+ objectGetter = mh;
+ } else {
+ objectSetter = mh;
+ }
+ }
+ }
+
+ MethodHandle getInner(final boolean isPrimitive, final boolean isGetter) {
+ if (isPrimitive) {
+ return isGetter ? primitiveGetter : primitiveSetter;
+ }
+ return isGetter ? objectGetter : objectSetter;
+ }
+ }
+
+ private static MethodHandle primitiveGetter(final int slot) {
+ return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, true);
+ }
+ private static MethodHandle primitiveSetter(final int slot) {
+ return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, false);
+ }
+ private static MethodHandle objectGetter(final int slot) {
+ return Accessors.getCached(slot, false, true);
+ }
+ private static MethodHandle objectSetter(final int slot) {
+ return Accessors.getCached(slot, false, false);
+ }
+
+ /**
+ * Constructor for spill properties. Array getters and setters will be created on demand.
+ *
+ * @param key the property key
+ * @param flags the property flags
+ * @param slot spill slot
+ */
+ public SpillProperty(final String key, final int flags, final int slot) {
+ super(key, flags, slot, primitiveGetter(slot), primitiveSetter(slot), objectGetter(slot), objectSetter(slot));
+ assert !OBJECT_FIELDS_ONLY || getLocalType() == Object.class;
+ }
+
+ SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
+ this(key, flags, slot);
+ setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
+ }
+
+ SpillProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
+ this(key, flags, slot);
+ setInitialValue(owner, initialValue);
+ }
+
+ /**
+ * Copy constructor
+ * @param property other property
+ */
+ protected SpillProperty(final SpillProperty property) {
+ super(property);
+ }
+
+ /**
+ * Copy constructor
+ * @param newType new type
+ * @param property other property
+ */
+ protected SpillProperty(final SpillProperty property, final Class<?> newType) {
+ super(property, newType);
+ }
+
+ @Override
+ public Property copy() {
+ return new SpillProperty(this);
+ }
+
+ @Override
+ public Property copy(final Class<?> newType) {
+ return new SpillProperty(this, newType);
+ }
+
+ @Override
+ public boolean isSpill() {
+ return true;
+ }
+
+ @Override
+ void initMethodHandles(final Class<?> structure) {
+ final int slot = getSlot();
+ primitiveGetter = primitiveGetter(slot);
+ primitiveSetter = primitiveSetter(slot);
+ objectGetter = objectGetter(slot);
+ objectSetter = objectSetter(slot);
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/CompiledScript.java b/src/jdk/nashorn/internal/runtime/StoredScript.java
index 6bb8e9a0..14a0ced0 100644
--- a/src/jdk/nashorn/internal/runtime/CompiledScript.java
+++ b/src/jdk/nashorn/internal/runtime/StoredScript.java
@@ -27,12 +27,16 @@ package jdk.nashorn.internal.runtime;
import java.io.Serializable;
import java.util.Arrays;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
- * Class representing a compiled script.
+ * Class representing a persistent compiled script.
*/
-final class CompiledScript implements Serializable {
+public final class StoredScript implements Serializable {
+
+ /** Compilation id */
+ private final int compilationId;
/** Main class name. */
private final String mainClassName;
@@ -43,23 +47,34 @@ final class CompiledScript implements Serializable {
/** Constants array. */
private final Object[] constants;
- /** The source */
- private transient Source source;
+ /** Function initializers */
+ private final Map<Integer, FunctionInitializer> initializers;
private static final long serialVersionUID = 2958227232195298340L;
/**
* Constructor.
*
+ * @param compilationId compilation id
* @param mainClassName main class name
* @param classBytes map of class names to class bytes
+ * @param initializers initializer map, id -> FunctionInitializer
* @param constants constants array
*/
- CompiledScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) {
- this.source = source;
+ public StoredScript(final int compilationId, final String mainClassName, final Map<String, byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, final Object[] constants) {
+ this.compilationId = compilationId;
this.mainClassName = mainClassName;
this.classBytes = classBytes;
this.constants = constants;
+ this.initializers = initializers;
+ }
+
+ /**
+ * Get the compilation id for this StoredScript
+ * @return compilation id
+ */
+ public int getCompilationId() {
+ return compilationId;
}
/**
@@ -75,7 +90,11 @@ final class CompiledScript implements Serializable {
* @return map of class bytes
*/
public Map<String, byte[]> getClassBytes() {
- return classBytes;
+ final Map<String, byte[]> clonedMap = new LinkedHashMap<>();
+ for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
+ clonedMap.put(entry.getKey(), entry.getValue().clone());
+ }
+ return clonedMap;
}
/**
@@ -83,23 +102,19 @@ final class CompiledScript implements Serializable {
* @return constants array
*/
public Object[] getConstants() {
- return constants;
+ return constants.clone();
}
/**
- * Returns the source of this cached script.
- * @return the source
+ * Returns the function initializers map.
+ * @return The initializers map.
*/
- public Source getSource() {
- return source;
- }
-
- /**
- * Sets the source of this cached script.
- * @param source the source
- */
- void setSource(final Source source) {
- this.source = source;
+ public Map<Integer, FunctionInitializer> getInitializers() {
+ final Map<Integer, FunctionInitializer> clonedMap = new LinkedHashMap<>();
+ for (final Map.Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
+ clonedMap.put(entry.getKey(), new FunctionInitializer(entry.getValue()));
+ }
+ return clonedMap;
}
@Override
@@ -111,15 +126,15 @@ final class CompiledScript implements Serializable {
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
- if (!(obj instanceof CompiledScript)) {
+ if (!(obj instanceof StoredScript)) {
return false;
}
- final CompiledScript cs = (CompiledScript) obj;
+ final StoredScript cs = (StoredScript) obj;
return mainClassName.equals(cs.mainClassName)
&& classBytes.equals(cs.classBytes)
&& Arrays.equals(constants, cs.constants);
diff --git a/src/jdk/nashorn/internal/runtime/Timing.java b/src/jdk/nashorn/internal/runtime/Timing.java
index aa32f1c4..e1d464d9 100644
--- a/src/jdk/nashorn/internal/runtime/Timing.java
+++ b/src/jdk/nashorn/internal/runtime/Timing.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,69 +24,69 @@
*/
package jdk.nashorn.internal.runtime;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
-import jdk.nashorn.internal.runtime.options.Options;
+import jdk.nashorn.internal.codegen.CompileUnit;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Simple wallclock timing framework
*/
-public final class Timing {
- private static final boolean ENABLED = Options.getBooleanProperty("nashorn.time");
- private static final Map<String, Long> TIMINGS;
- private static final long START_TIME;
-
- static {
- if (ENABLED) {
- TIMINGS = new LinkedHashMap<>();
- START_TIME = System.currentTimeMillis();
- Runtime.getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- final long t = System.currentTimeMillis();
- long knownTime = 0L;
- int maxLength = 0;
-
- for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
- maxLength = Math.max(maxLength, entry.getKey().length());
- }
- maxLength++;
-
- for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
- final StringBuilder sb = new StringBuilder();
-
- sb.append(entry.getKey());
- while (sb.length() < maxLength) {
- sb.append(' ');
- }
-
- final long duration = entry.getValue();
- sb.append(duration);
- sb.append(' ');
- sb.append(" ms");
-
- knownTime += duration;
-
- System.err.println(sb.toString()); //Context err is gone by shutdown TODO
- }
-
- final long total = t - START_TIME;
- System.err.println("Total runtime: " + total + " ms (Non-runtime: " + knownTime + " ms [" + (int)(knownTime * 100.0 / total) + "%])");
- }
- });
- } else {
- TIMINGS = null;
- START_TIME = 0L;
- }
+@Logger(name="time")
+public final class Timing implements Loggable {
+
+ private DebugLogger log;
+ private TimeSupplier timeSupplier;
+ private final boolean isEnabled;
+ private final long startTime;
+
+ private static final String LOGGER_NAME = Timing.class.getAnnotation(Logger.class).name();
+
+ /**
+ * Instantiate singleton timer for ScriptEnvironment
+ * @param isEnabled true if enabled, otherwise we keep the instance around
+ * for code brevity and "isEnabled" checks, but never instantiate anything
+ * inside it
+ */
+ public Timing(final boolean isEnabled) {
+ this.isEnabled = isEnabled;
+ this.startTime = System.nanoTime();
+ }
+
+ /**
+ * Get the log info accumulated by this Timing instance
+ * @return log info as one string
+ */
+ public String getLogInfo() {
+ assert isEnabled();
+ return timeSupplier.get();
+ }
+
+ /**
+ * Get the log info accumulated by this Timing instance
+ * @return log info as and array of strings, one per line
+ */
+ public String[] getLogInfoLines() {
+ assert isEnabled();
+ return timeSupplier.getStrings();
}
/**
- * Check if timing is inabled
+ * Check if timing is enabled
* @return true if timing is enabled
*/
- public static boolean isEnabled() {
- return ENABLED;
+ boolean isEnabled() {
+ return isEnabled;
}
/**
@@ -94,16 +94,150 @@ public final class Timing {
* or add to its accumulated time
*
* @param module module name
- * @param duration duration to add to accumulated time for module
+ * @param durationNano duration to add to accumulated time for module, in nanoseconds.
*/
- public static void accumulateTime(final String module, final long duration) {
- if (Timing.isEnabled()) {
- Long accumulatedTime = TIMINGS.get(module);
+ public void accumulateTime(final String module, final long durationNano) {
+ if (isEnabled()) {
+ ensureInitialized(Context.getContextTrusted());
+ timeSupplier.accumulateTime(module, durationNano);
+ }
+ }
+
+ private DebugLogger ensureInitialized(final Context context) {
+ //lazy init, as there is not necessarily a context available when
+ //a ScriptEnvironment gets initialize
+ if (isEnabled() && log == null) {
+ log = initLogger(context);
+ if (log.isEnabled()) {
+ this.timeSupplier = new TimeSupplier();
+ Runtime.getRuntime().addShutdownHook(
+ new Thread() {
+ @Override
+ public void run() {
+ //System.err.println because the context and the output streams may be gone
+ //when the shutdown hook executes
+ final StringBuilder sb = new StringBuilder();
+ for (final String str : timeSupplier.getStrings()) {
+ sb.append('[').
+ append(Timing.getLoggerName()).
+ append("] ").
+ append(str).
+ append('\n');
+ }
+ System.err.print(sb);
+ }
+ });
+ }
+ }
+ return log;
+ }
+
+ static String getLoggerName() {
+ return LOGGER_NAME;
+ }
+
+ @Override
+ public DebugLogger initLogger(final Context context) {
+ return context.getLogger(this.getClass());
+ }
+
+ @Override
+ public DebugLogger getLogger() {
+ return log;
+ }
+
+ /**
+ * Takes a duration in nanoseconds, and returns a string representation of it rounded to milliseconds.
+ * @param durationNano duration in nanoseconds
+ * @return the string representing the duration in milliseconds.
+ */
+ public static String toMillisPrint(final long durationNano) {
+ return Long.toString(TimeUnit.NANOSECONDS.toMillis(durationNano));
+ }
+
+ final class TimeSupplier implements Supplier<String> {
+ private final Map<String, Long> timings;
+
+ TimeSupplier() {
+ timings = new LinkedHashMap<>();
+ }
+
+ String[] getStrings() {
+ final List<String> strs = new ArrayList<>();
+ final BufferedReader br = new BufferedReader(new StringReader(get()));
+ String line;
+ try {
+ while ((line = br.readLine()) != null) {
+ strs.add(line);
+ }
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ return strs.toArray(new String[strs.size()]);
+ }
+
+ @Override
+ public String get() {
+ final long t = System.nanoTime();
+
+ long knownTime = 0L;
+ int maxKeyLength = 0;
+ int maxValueLength = 0;
+
+ for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+ maxKeyLength = Math.max(maxKeyLength, entry.getKey().length());
+ maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length());
+ }
+ maxKeyLength++;
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Accumulated compilation phase timings:\n\n");
+ for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+ int len;
+
+ len = sb.length();
+ sb.append(entry.getKey());
+ len = sb.length() - len;
+
+ while (len++ < maxKeyLength) {
+ sb.append(' ');
+ }
+
+ final Long duration = entry.getValue();
+ final String strDuration = toMillisPrint(duration);
+ len = strDuration.length();
+ for (int i = 0; i < maxValueLength - len; i++) {
+ sb.append(' ');
+ }
+
+ sb.append(strDuration).
+ append(" ms\n");
+
+ knownTime += duration;
+ }
+
+ final long total = t - startTime;
+ sb.append('\n');
+ sb.append("Total runtime: ").
+ append(toMillisPrint(total)).
+ append(" ms (Non-runtime: ").
+ append(toMillisPrint(knownTime)).
+ append(" ms [").
+ append((int)(knownTime * 100.0 / total)).
+ append("%])");
+
+ sb.append("\n\nEmitted compile units: ").
+ append(CompileUnit.getEmittedUnitCount());
+
+ return sb.toString();
+ }
+
+ private void accumulateTime(final String module, final long duration) {
+ Long accumulatedTime = timings.get(module);
if (accumulatedTime == null) {
accumulatedTime = 0L;
}
- TIMINGS.put(module, accumulatedTime + duration);
+ timings.put(module, accumulatedTime + duration);
}
}
-
}
diff --git a/src/jdk/nashorn/internal/runtime/Undefined.java b/src/jdk/nashorn/internal/runtime/Undefined.java
index a19c2445..57c7e5f1 100644
--- a/src/jdk/nashorn/internal/runtime/Undefined.java
+++ b/src/jdk/nashorn/internal/runtime/Undefined.java
@@ -25,16 +25,16 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
* Unique instance of this class is used to represent JavaScript undefined.
@@ -110,13 +110,13 @@ public final class Undefined extends DefaultPropertyAccess {
if (desc.getNameTokenCount() < 3) {
return findGetIndexMethod(desc);
}
- throw lookupTypeError("cant.read.property.of.undefined", desc);
+ return findGetMethod(desc);
case "setProp":
case "setElem":
if (desc.getNameTokenCount() < 3) {
return findSetIndexMethod(desc);
}
- throw lookupTypeError("cant.set.property.of.undefined", desc);
+ return findSetMethod(desc);
default:
break;
}
@@ -128,44 +128,23 @@ public final class Undefined extends DefaultPropertyAccess {
return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
}
- /**
- * Find the appropriate GETINDEX method for an invoke dynamic call.
- * @param desc The invoke dynamic callsite descriptor
- * @param args arguments
- * @return GuardedInvocation to be invoked at call site.
- */
- private static GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final Object... args) {
- final MethodType callType = desc.getMethodType();
- final Class<?> returnClass = callType.returnType();
- final Class<?> keyClass = callType.parameterType(1);
-
- String name = "get";
- if (returnClass.isPrimitive()) {
- //turn e.g. get with a double into getDouble
- final String returnTypeName = returnClass.getName();
- name += Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
- }
- MethodHandle methodHandle = findOwnMH(name, returnClass, keyClass);
- methodHandle = MH.asType(methodHandle, methodHandle.type().changeParameterType(0, Object.class));
+ private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
+ private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, int.class), 3, NashornCallSiteDescriptor.CALLSITE_STRICT);
- return new GuardedInvocation(methodHandle, UNDEFINED_GUARD);
+ private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
+ return new GuardedInvocation(MH.insertArguments(GET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
}
- /**
- * Find the appropriate SETINDEX method for an invoke dynamic call.
- * @param desc The invoke dynamic callsite descriptor
- * @return GuardedInvocation to be invoked at call site.
- */
- private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) {
- final MethodType callType = desc.getMethodType();
- final Class<?> keyClass = callType.parameterType(1);
- final Class<?> valueClass = callType.parameterType(2);
+ private static GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc) {
+ return new GuardedInvocation(GET_METHOD, UNDEFINED_GUARD).asType(desc);
+ }
- MethodHandle methodHandle = findOwnMH("set", void.class, keyClass, valueClass, boolean.class);
- methodHandle = MH.asType(methodHandle, methodHandle.type().changeParameterType(0, Object.class));
- methodHandle = MH.insertArguments(methodHandle, 3, false);
+ private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
+ return new GuardedInvocation(MH.insertArguments(SET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
+ }
- return new GuardedInvocation(methodHandle, UNDEFINED_GUARD);
+ private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) {
+ return new GuardedInvocation(SET_METHOD, UNDEFINED_GUARD).asType(desc);
}
@Override
@@ -174,7 +153,7 @@ public final class Undefined extends DefaultPropertyAccess {
}
@Override
- public void set(final Object key, final Object value, final boolean strict) {
+ public void set(final Object key, final Object value, final int flags) {
throw typeError("cant.set.property.of.undefined", ScriptRuntime.safeToString(key));
}
diff --git a/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java b/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java
new file mode 100644
index 00000000..53ea7f72
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * This exception is thrown from an optimistic operation, e.g. an integer add,
+ * that was to optimistic for what really took place. Typically things like
+ * trying to get an array element that we want to be an int, and it was a double,
+ * and an int add that actually overflows and needs a double for the representation
+ */
+
+@SuppressWarnings("serial")
+public final class UnwarrantedOptimismException extends RuntimeException {
+ /** Denotes an invalid program point */
+ public static final int INVALID_PROGRAM_POINT = -1;
+
+ /** The value for the first ordinary program point */
+ public static final int FIRST_PROGRAM_POINT = 1;
+
+ private Object returnValue;
+ private final int programPoint;
+ private final Type returnType;
+
+ /**
+ * Constructor
+ * @param returnValue actual return value from the too narrow operation
+ * @param programPoint program point where unwarranted optimism was detected
+ */
+ public UnwarrantedOptimismException(final Object returnValue, final int programPoint) {
+ this(returnValue, programPoint, getReturnType(returnValue));
+ }
+
+ /**
+ * Check if a program point is valid
+ * @param programPoint the program point
+ * @return true if valid
+ */
+ public static boolean isValid(final int programPoint) {
+ assert programPoint >= INVALID_PROGRAM_POINT;
+ return programPoint != INVALID_PROGRAM_POINT;
+ }
+
+ private static Type getReturnType(final Object v) {
+ if (v instanceof Double) {
+ return Type.NUMBER;
+ } else if (v instanceof Long) {
+ return Type.LONG;
+ }
+ assert !(v instanceof Integer) : v + " is an int"; // Can't have an unwarranted optimism exception with int
+ return Type.OBJECT;
+ }
+
+ /**
+ * Constructor with explicit return value type.
+ * @param returnValue actual return value from the too narrow operation
+ * @param programPoint program point where unwarranted optimism was detected
+ * @param returnType type of the returned value. Used to disambiguate the return type. E.g. an {@code ObjectArrayData}
+ * might return a {@link Double} for a particular element getter, but still throw this exception even if the call
+ * site can accept a double, since the array's type is actually {@code Type#OBJECT}. In this case, it must
+ * explicitly use this constructor to indicate its values are to be considered {@code Type#OBJECT} and not
+ * {@code Type#NUMBER}.
+ */
+ public UnwarrantedOptimismException(final Object returnValue, final int programPoint, final Type returnType) {
+ super("", null, false, Context.DEBUG);
+ assert returnType != Type.OBJECT || returnValue == null || !Type.typeFor(returnValue.getClass()).isNumeric();
+ assert returnType != Type.INT;
+ this.returnValue = returnValue;
+ this.programPoint = programPoint;
+ this.returnType = returnType;
+ }
+
+ /**
+ * Get the return value. This is a destructive readout, after the method is invoked the return value is null'd out.
+ * @return return value
+ */
+ public Object getReturnValueDestructive() {
+ final Object retval = returnValue;
+ returnValue = null;
+ return retval;
+ }
+
+ Object getReturnValueNonDestructive() {
+ return returnValue;
+ }
+
+ /**
+ * Get the return type
+ * @return return type
+ */
+ public Type getReturnType() {
+ return returnType;
+ }
+
+ /**
+ * Does this exception refer to an invalid program point? This might be OK if
+ * we throw it, e.g. from a parameter guard
+ * @return true if invalid program point specified
+ */
+ public boolean hasInvalidProgramPoint() {
+ return programPoint == INVALID_PROGRAM_POINT;
+ }
+
+ /**
+ * Get the program point
+ * @return the program point
+ */
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ /**
+ * Check if we ended up with a primitive return value (even though it may be
+ * too wide for what we tried to do, e.g. double instead of int)
+ * @return true if return value is primitive
+ */
+ public boolean hasPrimitiveReturnValue() {
+ return returnValue instanceof Number || returnValue instanceof Boolean;
+ }
+
+ @Override
+ public String getMessage() {
+ return "UNWARRANTED OPTIMISM: [returnValue=" +
+ returnValue +
+ " (class=" +
+ (returnValue == null ? "null" : returnValue.getClass().getSimpleName()) +
+ (hasInvalidProgramPoint() ?
+ " <invalid program point>" :
+ (" @ program point #" + programPoint)) +
+ ")]";
+ }
+
+
+ private void writeObject(final ObjectOutputStream out) throws NotSerializableException {
+ throw new NotSerializableException(getClass().getName());
+ }
+
+ private void readObject(final ObjectInputStream in) throws NotSerializableException {
+ throw new NotSerializableException(getClass().getName());
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
index 5b21f6ee..d14dd8e7 100644
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@@ -25,165 +25,214 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.util.concurrent.Callable;
-
-import jdk.nashorn.internal.codegen.CompilerConstants;
+import java.lang.invoke.MethodType;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
-import jdk.nashorn.internal.objects.Global;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
/**
* Property with user defined getters/setters. Actual getter and setter
* functions are stored in underlying ScriptObject. Only the 'slot' info is
* stored in the property.
- *
- * The slots here denote either ScriptObject embed field number or spill
- * array index. For spill array index, we use slot value of
- * (index + ScriptObject.embedSize). See also ScriptObject.getEmbedOrSpill
- * method. Negative slot value means that the corresponding getter or setter
- * is null. Note that always two slots are allocated in ScriptObject - but
- * negative (less by 1) slot number is stored for null getter or setter.
- * This is done so that when the property is redefined with a different
- * getter and setter (say, both non-null), we'll have spill slots to store
- * those. When a slot is negative, (-slot - 1) is the embed/spill index.
*/
-public final class UserAccessorProperty extends Property {
+public final class UserAccessorProperty extends SpillProperty {
- /** User defined getter function slot. */
- private final int getterSlot;
+ private static final long serialVersionUID = -5928687246526840321L;
- /** User defined setter function slot. */
- private final int setterSlot;
+ static final class Accessors {
+ Object getter;
+ Object setter;
- /** Getter method handle */
- private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
- "userAccessorGetter", Object.class, ScriptObject.class, int.class, Object.class);
+ Accessors(final Object getter, final Object setter) {
+ set(getter, setter);
+ }
- /** Setter method handle */
- private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
- "userAccessorSetter", void.class, ScriptObject.class, int.class, String.class, Object.class, Object.class);
+ final void set(final Object getter, final Object setter) {
+ this.getter = getter;
+ this.setter = setter;
+ }
+
+ @Override
+ public String toString() {
+ return "[getter=" + getter + " setter=" + setter + ']';
+ }
+ }
- /** Dynamic invoker for getter */
- private static final Object INVOKE_UA_GETTER = new Object();
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
- private static MethodHandle getINVOKE_UA_GETTER() {
+ /** Getter method handle */
+ private final static MethodHandle INVOKE_OBJECT_GETTER = findOwnMH_S("invokeObjectGetter", Object.class, Accessors.class, MethodHandle.class, Object.class);
+ private final static MethodHandle INVOKE_INT_GETTER = findOwnMH_S("invokeIntGetter", int.class, Accessors.class, MethodHandle.class, int.class, Object.class);
+ private final static MethodHandle INVOKE_LONG_GETTER = findOwnMH_S("invokeLongGetter", long.class, Accessors.class, MethodHandle.class, int.class, Object.class);
+ private final static MethodHandle INVOKE_NUMBER_GETTER = findOwnMH_S("invokeNumberGetter", double.class, Accessors.class, MethodHandle.class, int.class, Object.class);
- return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER,
- new Callable<MethodHandle>() {
- @Override
- public MethodHandle call() {
- return Bootstrap.createDynamicInvoker("dyn:call", Object.class,
- Object.class, Object.class);
- }
- });
+ /** Setter method handle */
+ private final static MethodHandle INVOKE_OBJECT_SETTER = findOwnMH_S("invokeObjectSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, Object.class);
+ private final static MethodHandle INVOKE_INT_SETTER = findOwnMH_S("invokeIntSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, int.class);
+ private final static MethodHandle INVOKE_LONG_SETTER = findOwnMH_S("invokeLongSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, long.class);
+ private final static MethodHandle INVOKE_NUMBER_SETTER = findOwnMH_S("invokeNumberSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, double.class);
+
+
+ static MethodHandle getINVOKE_UA_GETTER(final Class<?> returnType, final int programPoint) {
+ if (UnwarrantedOptimismException.isValid(programPoint)) {
+ final int flags = NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC | programPoint << CALLSITE_PROGRAM_POINT_SHIFT;
+ return Bootstrap.createDynamicInvoker("dyn:call", flags, returnType, Object.class, Object.class);
+ } else {
+ return Bootstrap.createDynamicInvoker("dyn:call", Object.class, Object.class, Object.class);
+ }
}
- /** Dynamic invoker for setter */
- private static Object INVOKE_UA_SETTER = new Object();
- private static MethodHandle getINVOKE_UA_SETTER() {
- return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
- new Callable<MethodHandle>() {
- @Override
- public MethodHandle call() {
- return Bootstrap.createDynamicInvoker("dyn:call", void.class,
- Object.class, Object.class, Object.class);
- }
- });
+ static MethodHandle getINVOKE_UA_SETTER(final Class<?> valueType) {
+ return Bootstrap.createDynamicInvoker("dyn:call", void.class, Object.class, Object.class, valueType);
}
/**
* Constructor
*
- * @param key property key
- * @param flags property flags
- * @param getterSlot getter slot, starting at first embed
- * @param setterSlot setter slot, starting at first embed
+ * @param key property key
+ * @param flags property flags
+ * @param slot spill slot
*/
- UserAccessorProperty(final String key, final int flags, final int getterSlot, final int setterSlot) {
- super(key, flags, -1);
- this.getterSlot = getterSlot;
- this.setterSlot = setterSlot;
+ UserAccessorProperty(final String key, final int flags, final int slot) {
+ super(key, flags, slot);
}
private UserAccessorProperty(final UserAccessorProperty property) {
super(property);
- this.getterSlot = property.getterSlot;
- this.setterSlot = property.setterSlot;
- }
-
- /**
- * Return getter spill slot for this UserAccessorProperty.
- * @return getter slot
- */
- public int getGetterSlot() {
- return getterSlot;
}
- /**
- * Return setter spill slot for this UserAccessorProperty.
- * @return setter slot
- */
- public int getSetterSlot() {
- return setterSlot;
+ private UserAccessorProperty(final UserAccessorProperty property, final Class<?> newType) {
+ super(property, newType);
}
@Override
- protected Property copy() {
+ public Property copy() {
return new UserAccessorProperty(this);
}
@Override
- public boolean equals(final Object other) {
- if (!super.equals(other)) {
- return false;
+ public Property copy(final Class<?> newType) {
+ return new UserAccessorProperty(this, newType);
+ }
+
+ void setAccessors(final ScriptObject sobj, final PropertyMap map, final Accessors gs) {
+ try {
+ //invoke the getter and find out
+ super.getSetter(Object.class, map).invokeExact((Object)sobj, (Object)gs);
+ } catch (final Error | RuntimeException t) {
+ throw t;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
}
+ }
- final UserAccessorProperty uc = (UserAccessorProperty) other;
- return getterSlot == uc.getterSlot && setterSlot == uc.setterSlot;
+ //pick the getter setter out of the correct spill slot in sobj
+ Accessors getAccessors(final ScriptObject sobj) {
+ try {
+ //invoke the super getter with this spill slot
+ //get the getter setter from the correct spill slot
+ final Object gs = super.getGetter(Object.class).invokeExact((Object)sobj);
+ return (Accessors)gs;
+ } catch (final Error | RuntimeException t) {
+ throw t;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
}
@Override
- public int hashCode() {
- return super.hashCode() ^ getterSlot ^ setterSlot;
+ protected Class<?> getLocalType() {
+ return Object.class;
+ }
+
+ @Override
+ public boolean hasGetterFunction(final ScriptObject sobj) {
+ return getAccessors(sobj).getter != null;
+ }
+
+ @Override
+ public boolean hasSetterFunction(final ScriptObject sobj) {
+ return getAccessors(sobj).setter != null;
}
- /*
- * Accessors.
- */
@Override
- public int getSpillCount() {
- return 2;
+ public int getIntValue(final ScriptObject self, final ScriptObject owner) {
+ return (int)getObjectValue(self, owner);
}
@Override
- public boolean hasGetterFunction(final ScriptObject obj) {
- return obj.getSpill(getterSlot) != null;
+ public long getLongValue(final ScriptObject self, final ScriptObject owner) {
+ return (long)getObjectValue(self, owner);
}
@Override
- public boolean hasSetterFunction(final ScriptObject obj) {
- return obj.getSpill(setterSlot) != null;
+ public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
+ return (double)getObjectValue(self, owner);
}
@Override
public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
- return userAccessorGetter(owner, getGetterSlot(), self);
+ try {
+ return invokeObjectGetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_GETTER(Object.class, INVALID_PROGRAM_POINT), self);
+ } catch (final Error | RuntimeException t) {
+ throw t;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict) {
+ setValue(self, owner, (Object) value, strict);
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) {
+ setValue(self, owner, (Object) value, strict);
+ }
+
+ @Override
+ public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) {
+ setValue(self, owner, (Object) value, strict);
}
@Override
- public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
- userAccessorSetter(owner, getSetterSlot(), strict ? getKey() : null, self, value);
+ public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
+ try {
+ invokeObjectSetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_SETTER(Object.class), strict ? getKey() : null, self, value);
+ } catch (final Error | RuntimeException t) {
+ throw t;
+ } catch (final Throwable t) {
+ throw new RuntimeException(t);
+ }
}
@Override
public MethodHandle getGetter(final Class<?> type) {
- return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type);
+ //this returns a getter on the format (Accessors, Object receiver)
+ return Lookup.filterReturnType(INVOKE_OBJECT_GETTER, type);
+ }
+
+ @Override
+ public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
+ if (type == int.class) {
+ return INVOKE_INT_GETTER;
+ } else if (type == long.class) {
+ return INVOKE_LONG_GETTER;
+ } else if (type == double.class) {
+ return INVOKE_NUMBER_GETTER;
+ } else {
+ assert type == Object.class;
+ return INVOKE_OBJECT_GETTER;
+ }
}
@Override
@@ -192,58 +241,127 @@ public final class UserAccessorProperty extends Property {
}
@Override
- public ScriptFunction getGetterFunction(final ScriptObject obj) {
- final Object value = obj.getSpill(getterSlot);
- return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
+ public ScriptFunction getGetterFunction(final ScriptObject sobj) {
+ final Object value = getAccessors(sobj).getter;
+ return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
}
@Override
public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
- return USER_ACCESSOR_SETTER.methodHandle();
+ if (type == int.class) {
+ return INVOKE_INT_SETTER;
+ } else if (type == long.class) {
+ return INVOKE_LONG_SETTER;
+ } else if (type == double.class) {
+ return INVOKE_NUMBER_SETTER;
+ } else {
+ assert type == Object.class;
+ return INVOKE_OBJECT_SETTER;
+ }
}
@Override
- public ScriptFunction getSetterFunction(final ScriptObject obj) {
- final Object value = obj.getSpill(setterSlot);
- return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
+ public ScriptFunction getSetterFunction(final ScriptObject sobj) {
+ final Object value = getAccessors(sobj).setter;
+ return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
+ }
+
+ /**
+ * Get the getter for the {@code Accessors} object.
+ * This is the the super {@code Object} type getter with {@code Accessors} return type.
+ *
+ * @return The getter handle for the Accessors
+ */
+ MethodHandle getAccessorsGetter() {
+ return super.getGetter(Object.class).asType(MethodType.methodType(Accessors.class, Object.class));
}
// User defined getter and setter are always called by "dyn:call". Note that the user
// getter/setter may be inherited. If so, proto is bound during lookup. In either
// inherited or self case, slot is also bound during lookup. Actual ScriptFunction
// to be called is retrieved everytime and applied.
- static Object userAccessorGetter(final ScriptObject proto, final int slot, final Object self) {
- final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
- final Object func = container.getSpill(slot);
-
+ @SuppressWarnings("unused")
+ private static Object invokeObjectGetter(final Accessors gs, final MethodHandle invoker, final Object self) throws Throwable {
+ final Object func = gs.getter;
if (func instanceof ScriptFunction) {
- try {
- return getINVOKE_UA_GETTER().invokeExact(func, self);
- } catch(final Error|RuntimeException t) {
- throw t;
- } catch(final Throwable t) {
- throw new RuntimeException(t);
- }
+ return invoker.invokeExact(func, self);
}
return UNDEFINED;
}
- static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
- final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
- final Object func = container.getSpill(slot);
+ @SuppressWarnings("unused")
+ private static int invokeIntGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
+ final Object func = gs.getter;
+ if (func instanceof ScriptFunction) {
+ return (int) invoker.invokeExact(func, self);
+ }
+
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ @SuppressWarnings("unused")
+ private static long invokeLongGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
+ final Object func = gs.getter;
+ if (func instanceof ScriptFunction) {
+ return (long) invoker.invokeExact(func, self);
+ }
+
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ @SuppressWarnings("unused")
+ private static double invokeNumberGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
+ final Object func = gs.getter;
+ if (func instanceof ScriptFunction) {
+ return (double) invoker.invokeExact(func, self);
+ }
+
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ @SuppressWarnings("unused")
+ private static void invokeObjectSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final Object value) throws Throwable {
+ final Object func = gs.setter;
+ if (func instanceof ScriptFunction) {
+ invoker.invokeExact(func, self, value);
+ } else if (name != null) {
+ throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static void invokeIntSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final int value) throws Throwable {
+ final Object func = gs.setter;
+ if (func instanceof ScriptFunction) {
+ invoker.invokeExact(func, self, value);
+ } else if (name != null) {
+ throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
+ }
+ }
+ @SuppressWarnings("unused")
+ private static void invokeLongSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final long value) throws Throwable {
+ final Object func = gs.setter;
if (func instanceof ScriptFunction) {
- try {
- getINVOKE_UA_SETTER().invokeExact(func, self, value);
- } catch(final Error|RuntimeException t) {
- throw t;
- } catch(final Throwable t) {
- throw new RuntimeException(t);
- }
- } else if (name != null) {
+ invoker.invokeExact(func, self, value);
+ } else if (name != null) {
throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
}
}
+ @SuppressWarnings("unused")
+ private static void invokeNumberSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final double value) throws Throwable {
+ final Object func = gs.setter;
+ if (func instanceof ScriptFunction) {
+ invoker.invokeExact(func, self, value);
+ } else if (name != null) {
+ throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
+ }
+ }
+
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(LOOKUP, UserAccessorProperty.class, name, MH.type(rtype, types));
+ }
+
}
diff --git a/src/jdk/nashorn/internal/runtime/WithObject.java b/src/jdk/nashorn/internal/runtime/WithObject.java
index dc48d727..20510dfd 100644
--- a/src/jdk/nashorn/internal/runtime/WithObject.java
+++ b/src/jdk/nashorn/internal/runtime/WithObject.java
@@ -35,6 +35,8 @@ import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -64,7 +66,6 @@ public final class WithObject extends ScriptObject implements Scope {
this.expression = expression;
}
-
/**
* Delete a property based on a key.
* @param key Any valid JavaScript value.
@@ -98,11 +99,11 @@ public final class WithObject extends ScriptObject implements Scope {
final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
FindProperty find = null;
GuardedInvocation link = null;
- ScriptObject self = null;
+ ScriptObject self;
final boolean isNamedOperation;
final String name;
- if(desc.getNameTokenCount() > 2) {
+ if (desc.getNameTokenCount() > 2) {
isNamedOperation = true;
name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
} else {
@@ -117,7 +118,6 @@ public final class WithObject extends ScriptObject implements Scope {
if (find != null) {
link = self.lookup(desc, request);
-
if (link != null) {
return fixExpressionCallSite(ndesc, link);
}
@@ -193,18 +193,33 @@ public final class WithObject extends ScriptObject implements Scope {
*
* @param key Property key.
* @param deep Whether the search should look up proto chain.
- * @param stopOnNonScope should a deep search stop on the first non-scope object?
* @param start the object on which the lookup was originally initiated
*
* @return FindPropertyData or null if not found.
*/
@Override
- FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
- final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start);
+ FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
+ // We call findProperty on 'expression' with 'expression' itself as start parameter.
+ // This way in ScriptObject.setObject we can tell the property is from a 'with' expression
+ // (as opposed from another non-scope object in the proto chain such as Object.prototype).
+ final FindProperty exprProperty = expression.findProperty(key, true, expression);
if (exprProperty != null) {
return exprProperty;
}
- return super.findProperty(key, deep, stopOnNonScope, start);
+ return super.findProperty(key, deep, start);
+ }
+
+ @Override
+ protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+ FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true);
+ if (find != null) {
+ final Object func = find.getObjectValue();
+ if (func instanceof ScriptFunction) {
+ return ScriptRuntime.apply((ScriptFunction)func, expression, name);
+ }
+ }
+
+ return getProto().invokeNoSuchProperty(name, programPoint);
}
@Override
@@ -242,35 +257,65 @@ public final class WithObject extends ScriptObject implements Scope {
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
// If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
// expression.
- if(!"getMethod".equals(desc.getFirstOperator())) {
+ if (!"getMethod".equals(desc.getFirstOperator())) {
return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
}
- final MethodHandle linkInvocation = link.getInvocation();
- final MethodType linkType = linkInvocation.type();
- final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
+ final MethodHandle linkInvocation = link.getInvocation();
+ final MethodType linkType = linkInvocation.type();
+ final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
+
return link.replaceMethods(
// Make sure getMethod will bind the script functions it receives to WithObject.expression
- MH.foldArguments(linkReturnsFunction ? BIND_TO_EXPRESSION_FN : BIND_TO_EXPRESSION_OBJ,
- filter(linkInvocation.asType(linkType.changeReturnType(
- linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)),
- // No clever things for the guard -- it is still identically filtered.
- filterGuard(link, WITHEXPRESSIONFILTER));
+ MH.foldArguments(
+ linkReturnsFunction ?
+ BIND_TO_EXPRESSION_FN :
+ BIND_TO_EXPRESSION_OBJ,
+ filterReceiver(
+ linkInvocation.asType(
+ linkType.changeReturnType(
+ linkReturnsFunction ?
+ ScriptFunction.class :
+ Object.class).
+ changeParameterType(
+ 0,
+ Object.class)),
+ WITHEXPRESSIONFILTER)),
+ filterGuardReceiver(link, WITHEXPRESSIONFILTER));
+ // No clever things for the guard -- it is still identically filtered.
+
}
private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
- final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
- return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER),
- NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER)));
+ final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
+ final MethodHandle expressionGuard = expressionGuard(name, owner);
+ final MethodHandle filterGuardReceiver = filterGuardReceiver(newLink, WITHSCOPEFILTER);
+ return link.replaceMethods(
+ filterReceiver(
+ newLink.getInvocation(),
+ WITHSCOPEFILTER),
+ NashornGuards.combineGuards(
+ expressionGuard,
+ filterGuardReceiver));
}
- private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
+ private static MethodHandle filterGuardReceiver(final GuardedInvocation link, final MethodHandle receiverFilter) {
final MethodHandle test = link.getGuard();
- return test == null ? null : filter(test, filter);
+ if (test == null) {
+ return null;
+ }
+
+ final Class<?> receiverType = test.type().parameterType(0);
+ final MethodHandle filter = MH.asType(receiverFilter,
+ receiverFilter.type().changeParameterType(0, receiverType).
+ changeReturnType(receiverType));
+
+ return filterReceiver(test, filter);
}
- private static MethodHandle filter(final MethodHandle mh, final MethodHandle filter) {
- return MH.filterArguments(mh, 0, filter.asType(filter.type().changeReturnType(mh.type().parameterType(0))));
+ private static MethodHandle filterReceiver(final MethodHandle mh, final MethodHandle receiverFilter) {
+ //With expression filter == receiverFilter, i.e. receiver is cast to withobject and its expression returned
+ return MH.filterArguments(mh, 0, receiverFilter.asType(receiverFilter.type().changeReturnType(mh.type().parameterType(0))));
}
/**
@@ -284,11 +329,27 @@ public final class WithObject extends ScriptObject implements Scope {
@SuppressWarnings("unused")
private static Object bindToExpression(final Object fn, final Object receiver) {
- return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn;
+ if (fn instanceof ScriptFunction) {
+ return bindToExpression((ScriptFunction) fn, receiver);
+ } else if (fn instanceof ScriptObjectMirror) {
+ final ScriptObjectMirror mirror = (ScriptObjectMirror)fn;
+ if (mirror.isFunction()) {
+ // We need to make sure correct 'this' is used for calls with Ident call
+ // expressions. We do so here using an AbstractJSObject instance.
+ return new AbstractJSObject() {
+ @Override
+ public Object call(final Object thiz, final Object... args) {
+ return mirror.call(withFilterExpression(receiver), args);
+ }
+ };
+ }
+ }
+
+ return fn;
}
private static Object bindToExpression(final ScriptFunction fn, final Object receiver) {
- return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]);
+ return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
}
private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
diff --git a/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java b/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java
new file mode 100644
index 00000000..d9e01923
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.arrays;
+
+/**
+ * Marker interface for any ContinuousArray with any elements
+ * Used for type checks that throw ClassCastExceptions and force relinks
+ * for fast NativeArray specializations of builtin methods
+ */
+public interface AnyElements {
+ /**
+ * Return a numeric weight of the element type - wider is higher
+ * @return element type weight
+ */
+ public int getElementWeight();
+} \ No newline at end of file
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index 58f32968..f0a8c7a2 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -25,34 +25,227 @@
package jdk.nashorn.internal.runtime.arrays;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Array;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* ArrayData - abstraction for wrapping array elements
*/
public abstract class ArrayData {
-
/** Minimum chunk size for underlying arrays */
- protected static final int CHUNK_SIZE = 16;
+ protected static final int CHUNK_SIZE = 32;
/** Mask for getting a chunk */
protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
- /**
- * Immutable empty array to get ScriptObjects started.
- */
- public static final ArrayData EMPTY_ARRAY = new NoTypeArrayData();
+ /** Untouched data - still link callsites as IntArrayData, but expands to
+ * a proper ArrayData when we try to write to it */
+ public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
/**
* Length of the array data. Not necessarily length of the wrapped array.
+ * This is private to ensure that no one in a subclass is able to touch the length
+ * without going through {@link #setLength}. This is used to implement
+ * {@link LengthNotWritableFilter}s, ensuring that there are no ways past
+ * a {@link #setLength} function replaced by a nop
*/
private long length;
/**
+ * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
+ * of the wrong type
+ */
+ protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
+
+ /**
+ * Immutable empty array to get ScriptObjects started.
+ * Use the same array and convert it to mutable as soon as it is modified
+ */
+ private static class UntouchedArrayData extends ContinuousArrayData {
+ private UntouchedArrayData() {
+ super(0);
+ }
+
+ private ArrayData toRealArrayData() {
+ return toRealArrayData(0);
+ }
+
+ private ArrayData toRealArrayData(final int index) {
+ final IntArrayData newData = new IntArrayData(index + 1);
+ if (index == 0) {
+ return newData;
+ }
+ return new DeletedRangeArrayFilter(newData, 0, index);
+ }
+
+ @Override
+ public ContinuousArrayData copy() {
+ assert length() == 0;
+ return this;
+ }
+
+ @Override
+ public Object asArrayOfType(final Class<?> componentType) {
+ return Array.newInstance(componentType, 0);
+ }
+
+ @Override
+ public Object[] asObjectArray() {
+ return ScriptRuntime.EMPTY_ARRAY;
+ }
+
+ @Override
+ public ArrayData ensure(final long safeIndex) {
+ if (safeIndex > 0L) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
+ return new SparseArrayData(this, safeIndex + 1);
+ }
+ //known to fit in int
+ return toRealArrayData((int)safeIndex).ensure(safeIndex);
+ }
+ return this;
+ }
+
+ @Override
+ public ArrayData convert(final Class<?> type) {
+ return toRealArrayData(0).convert(type);
+ }
+
+ @Override
+ public ArrayData delete(final int index) {
+ return new DeletedRangeArrayFilter(this, index, index);
+ }
+
+ @Override
+ public ArrayData delete(final long fromIndex, final long toIndex) {
+ return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
+ }
+
+ @Override
+ public void shiftLeft(final int by) {
+ //nop, always empty or we wouldn't be of this class
+ }
+
+ @Override
+ public ArrayData shiftRight(final int by) {
+ return this; //always empty or we wouldn't be of this class
+ }
+
+ @Override
+ public ArrayData shrink(final long newLength) {
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return toRealArrayData(index).set(index, value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ return toRealArrayData(index).set(index, value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return toRealArrayData(index).set(index, value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return toRealArrayData(index).set(index, value, strict);
+ }
+
+ @Override
+ public int getInt(final int index) {
+ throw new ArrayIndexOutOfBoundsException(index); //empty
+ }
+
+ @Override
+ public long getLong(final int index) {
+ throw new ArrayIndexOutOfBoundsException(index); //empty
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ throw new ArrayIndexOutOfBoundsException(index); //empty
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ throw new ArrayIndexOutOfBoundsException(index); //empty
+ }
+
+ @Override
+ public boolean has(final int index) {
+ return false; //empty
+ }
+
+ @Override
+ public Object pop() {
+ return ScriptRuntime.UNDEFINED;
+ }
+
+ @Override
+ public ArrayData push(final boolean strict, final Object item) {
+ return toRealArrayData().push(strict, item);
+ }
+
+ @Override
+ public ArrayData slice(final long from, final long to) {
+ return this; //empty
+ }
+
+ @Override
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ return otherData.copy();
+ }
+
+ //no need to override fastPopInt, as the default behavior is to throw classcast exception so we
+ //can relink and return an undefined, this is the IntArrayData default behavior
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ return null;
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return null;
+ }
+
+ @Override
+ public Class<?> getElementType() {
+ return int.class;
+ }
+
+ @Override
+ public Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+ }
+
+ /**
* Constructor
* @param length Virtual length of the array.
*/
@@ -64,17 +257,37 @@ public abstract class ArrayData {
* Factory method for unspecified array - start as int
* @return ArrayData
*/
- public static ArrayData initialArray() {
+ public final static ArrayData initialArray() {
return new IntArrayData();
}
/**
+ * Unwarranted thrower
+ *
+ * @param data array data
+ * @param programPoint program point
+ * @param index array index
+ */
+ protected static void throwUnwarranted(final ArrayData data, final int programPoint, final int index) {
+ throw new UnwarrantedOptimismException(data.getObject(index), programPoint);
+ }
+
+ /**
+ * Align an array size up to the nearest array chunk size
+ * @param size size required
+ * @return size given, always >= size
+ */
+ protected final static int alignUp(final int size) {
+ return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
+ }
+
+ /**
* Factory method for unspecified array with given length - start as int array data
*
* @param length the initial length
* @return ArrayData
*/
- public static ArrayData allocate(final int length) {
+ public static final ArrayData allocate(final int length) {
if (length == 0) {
return new IntArrayData();
} else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
@@ -90,7 +303,7 @@ public abstract class ArrayData {
* @param array the array
* @return ArrayData wrapping this array
*/
- public static ArrayData allocate(final Object array) {
+ public static final ArrayData allocate(final Object array) {
final Class<?> clazz = array.getClass();
if (clazz == int[].class) {
@@ -110,7 +323,7 @@ public abstract class ArrayData {
* @param array the array to use for initial elements
* @return the ArrayData
*/
- public static ArrayData allocate(final int[] array) {
+ public static final ArrayData allocate(final int[] array) {
return new IntArrayData(array, array.length);
}
@@ -120,7 +333,7 @@ public abstract class ArrayData {
* @param array the array to use for initial elements
* @return the ArrayData
*/
- public static ArrayData allocate(final long[] array) {
+ public static final ArrayData allocate(final long[] array) {
return new LongArrayData(array, array.length);
}
@@ -130,7 +343,7 @@ public abstract class ArrayData {
* @param array the array to use for initial elements
* @return the ArrayData
*/
- public static ArrayData allocate(final double[] array) {
+ public static final ArrayData allocate(final double[] array) {
return new NumberArrayData(array, array.length);
}
@@ -140,7 +353,7 @@ public abstract class ArrayData {
* @param array the array to use for initial elements
* @return the ArrayData
*/
- public static ArrayData allocate(final Object[] array) {
+ public static final ArrayData allocate(final Object[] array) {
return new ObjectArrayData(array, array.length);
}
@@ -150,8 +363,8 @@ public abstract class ArrayData {
* @param buf the nio ByteBuffer to wrap
* @return the ArrayData
*/
- public static ArrayData allocate(final ByteBuffer buf) {
- return new ByteBufferArrayData((ByteBuffer)buf);
+ public static final ArrayData allocate(final ByteBuffer buf) {
+ return new ByteBufferArrayData(buf);
}
/**
@@ -160,7 +373,7 @@ public abstract class ArrayData {
* @param underlying the underlying ArrayData to wrap in the freeze filter
* @return the frozen ArrayData
*/
- public static ArrayData freeze(final ArrayData underlying) {
+ public static final ArrayData freeze(final ArrayData underlying) {
return new FrozenArrayFilter(underlying);
}
@@ -170,11 +383,31 @@ public abstract class ArrayData {
* @param underlying the underlying ArrayData to wrap in the seal filter
* @return the sealed ArrayData
*/
- public static ArrayData seal(final ArrayData underlying) {
+ public static final ArrayData seal(final ArrayData underlying) {
return new SealedArrayFilter(underlying);
}
/**
+ * Prevent this array from being extended
+ *
+ * @param underlying the underlying ArrayData to wrap in the non extensible filter
+ * @return new array data, filtered
+ */
+ public static final ArrayData preventExtension(final ArrayData underlying) {
+ return new NonExtensibleArrayFilter(underlying);
+ }
+
+ /**
+ * Prevent this array from having its length reset
+ *
+ * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
+ * @return new array data, filtered
+ */
+ public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
+ return new LengthNotWritableFilter(underlying);
+ }
+
+ /**
* Return the length of the array data. This may differ from the actual
* length of the array this wraps as length may be set or gotten as any
* other JavaScript Property
@@ -227,6 +460,22 @@ public abstract class ArrayData {
}
/**
+ * Increase length by 1
+ * @return the new length, not the old one (i.e. pre-increment)
+ */
+ protected final long increaseLength() {
+ return ++this.length;
+ }
+
+ /**
+ * Decrease length by 1.
+ * @return the new length, not the old one (i.e. pre-decrement)
+ */
+ protected final long decreaseLength() {
+ return --this.length;
+ }
+
+ /**
* Shift the array data left
*
* TODO: explore start at an index and not at zero, to make these operations
@@ -235,7 +484,7 @@ public abstract class ArrayData {
*
* @param by offset to shift
*/
- public abstract void shiftLeft(int by);
+ public abstract void shiftLeft(final int by);
/**
* Shift the array right
@@ -244,7 +493,7 @@ public abstract class ArrayData {
* @return New arraydata (or same)
*/
- public abstract ArrayData shiftRight(int by);
+ public abstract ArrayData shiftRight(final int by);
/**
* Ensure that the given index exists and won't fail subsequent
@@ -252,7 +501,7 @@ public abstract class ArrayData {
* @param safeIndex the index to ensure wont go out of bounds
* @return new array data (or same)
*/
- public abstract ArrayData ensure(long safeIndex);
+ public abstract ArrayData ensure(final long safeIndex);
/**
* Shrink the array to a new length, may or may not retain the
@@ -262,7 +511,7 @@ public abstract class ArrayData {
*
* @return new array data (or same)
*/
- public abstract ArrayData shrink(long newLength);
+ public abstract ArrayData shrink(final long newLength);
/**
* Set an object value at a given index
@@ -272,7 +521,7 @@ public abstract class ArrayData {
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, Object value, boolean strict);
+ public abstract ArrayData set(final int index, final Object value, final boolean strict);
/**
* Set an int value at a given index
@@ -282,7 +531,7 @@ public abstract class ArrayData {
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, int value, boolean strict);
+ public abstract ArrayData set(final int index, final int value, final boolean strict);
/**
* Set a long value at a given index
@@ -292,7 +541,7 @@ public abstract class ArrayData {
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, long value, boolean strict);
+ public abstract ArrayData set(final int index, final long value, final boolean strict);
/**
* Set an double value at a given index
@@ -302,7 +551,7 @@ public abstract class ArrayData {
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, double value, boolean strict);
+ public abstract ArrayData set(final int index, final double value, final boolean strict);
/**
* Set an empty value at a given index. Should only affect Object array.
@@ -333,7 +582,28 @@ public abstract class ArrayData {
* @param index the index
* @return the value
*/
- public abstract int getInt(int index);
+ public abstract int getInt(final int index);
+
+ /**
+ * Returns the optimistic type of this array data. Basically, when an array data object needs to throw an
+ * {@link UnwarrantedOptimismException}, this type is used as the actual type of the return value.
+ * @return the optimistic type of this array data.
+ */
+ public Type getOptimisticType() {
+ return Type.OBJECT;
+ }
+
+ /**
+ * Get optimistic int - default is that it's impossible. Overridden
+ * by arrays that actually represents ints
+ *
+ * @param index the index
+ * @param programPoint program point
+ * @return the value
+ */
+ public int getIntOptimistic(final int index, final int programPoint) {
+ throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+ }
/**
* Get a long value from a given index
@@ -341,7 +611,19 @@ public abstract class ArrayData {
* @param index the index
* @return the value
*/
- public abstract long getLong(int index);
+ public abstract long getLong(final int index);
+
+ /**
+ * Get optimistic long - default is that it's impossible. Overridden
+ * by arrays that actually represents longs or narrower
+ *
+ * @param index the index
+ * @param programPoint program point
+ * @return the value
+ */
+ public long getLongOptimistic(final int index, final int programPoint) {
+ throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+ }
/**
* Get a double value from a given index
@@ -349,7 +631,19 @@ public abstract class ArrayData {
* @param index the index
* @return the value
*/
- public abstract double getDouble(int index);
+ public abstract double getDouble(final int index);
+
+ /**
+ * Get optimistic double - default is that it's impossible. Overridden
+ * by arrays that actually represents doubles or narrower
+ *
+ * @param index the index
+ * @param programPoint program point
+ * @return the value
+ */
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+ }
/**
* Get an Object value from a given index
@@ -357,14 +651,14 @@ public abstract class ArrayData {
* @param index the index
* @return the value
*/
- public abstract Object getObject(int index);
+ public abstract Object getObject(final int index);
/**
* Tests to see if an entry exists (avoids boxing.)
* @param index the index
* @return true if entry exists
*/
- public abstract boolean has(int index);
+ public abstract boolean has(final int index);
/**
* Returns if element at specific index can be deleted or not.
@@ -410,7 +704,7 @@ public abstract class ArrayData {
* @param index the index
* @return new array data (or same)
*/
- public abstract ArrayData delete(int index);
+ public abstract ArrayData delete(final int index);
/**
* Delete a given range from this array;
@@ -420,7 +714,7 @@ public abstract class ArrayData {
*
* @return new ArrayData after deletion
*/
- public abstract ArrayData delete(long fromIndex, long toIndex);
+ public abstract ArrayData delete(final long fromIndex, final long toIndex);
/**
* Convert the ArrayData to one with a different element type
@@ -430,7 +724,7 @@ public abstract class ArrayData {
* @param type new element type
* @return new array data
*/
- protected abstract ArrayData convert(Class<?> type);
+ public abstract ArrayData convert(final Class<?> type);
/**
* Push an array of items to the end of the array
@@ -447,7 +741,7 @@ public abstract class ArrayData {
final Class<?> widest = widestType(items);
ArrayData newData = convert(widest);
- long pos = newData.length();
+ long pos = newData.length;
for (final Object item : items) {
newData = newData.ensure(pos); //avoid sparse array
newData.set((int)pos++, item, strict);
@@ -456,6 +750,50 @@ public abstract class ArrayData {
}
/**
+ * Push an array of items to the end of the array
+ *
+ * @param strict are we in strict mode
+ * @param item the item
+ * @return new array data (or same)
+ */
+ public ArrayData push(final boolean strict, final Object item) {
+ return push(strict, new Object[] { item });
+ }
+
+ /**
+ * Push an array of items to the end of the array
+ *
+ * @param strict are we in strict mode
+ * @param item the item
+ * @return new array data (or same)
+ */
+ public ArrayData push(final boolean strict, final double item) {
+ return push(strict, item);
+ }
+
+ /**
+ * Push an array of items to the end of the array
+ *
+ * @param strict are we in strict mode
+ * @param item the item
+ * @return new array data (or same)
+ */
+ public ArrayData push(final boolean strict, final long item) {
+ return push(strict, item);
+ }
+
+ /**
+ * Push an array of items to the end of the array
+ *
+ * @param strict are we in strict mode
+ * @param item the item
+ * @return new array data (or same)
+ */
+ public ArrayData push(final boolean strict, final int item) {
+ return push(strict, item);
+ }
+
+ /**
* Pop an element from the end of the array
*
* @return the popped element
@@ -470,7 +808,7 @@ public abstract class ArrayData {
* @param to end index + 1
* @return new array data
*/
- public abstract ArrayData slice(long from, long to);
+ public abstract ArrayData slice(final long from, final long to);
/**
* Fast splice operation. This just modifies the array according to the number of
@@ -482,30 +820,32 @@ public abstract class ArrayData {
* @param removed number of removed elements
* @param added number of added elements
* @throws UnsupportedOperationException if fast splice is not supported for the class or arguments.
+ * @return new arraydata, but this never happens because we always throw an exception
*/
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
-
static Class<?> widestType(final Object... items) {
assert items.length > 0;
Class<?> widest = Integer.class;
for (final Object item : items) {
- final Class<?> itemClass = item == null ? null : item.getClass();
+ if (item == null) {
+ return Object.class;
+ }
+ final Class<?> itemClass = item.getClass();
if (itemClass == Long.class) {
if (widest == Integer.class) {
widest = Long.class;
}
- } else if (itemClass == Double.class) {
+ } else if (itemClass == Double.class || itemClass == Float.class) {
if (widest == Integer.class || widest == Long.class) {
widest = Double.class;
}
- } else if (!(item instanceof Number)) {
- widest = Object.class;
- break;
+ } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) {
+ return Object.class;
}
}
@@ -513,23 +853,42 @@ public abstract class ArrayData {
}
/**
+ * Return a list of keys in the array for the iterators
+ * @return iterator key list
+ */
+ protected List<Long> computeIteratorKeys() {
+ final List<Long> keys = new ArrayList<>();
+
+ final long len = length();
+ for (long i = 0L; i < len; i = nextIndex(i)) {
+ if (has((int)i)) {
+ keys.add(i);
+ }
+ }
+
+ return keys;
+ }
+
+ /**
+ * Return an iterator that goes through all indexes of elements
+ * in this array. This includes those after array.length if
+ * they exist
+ *
+ * @return iterator
+ */
+ public Iterator<Long> indexIterator() {
+ return computeIteratorKeys().iterator();
+ }
+
+ /**
* Exponential growth function for array size when in
* need of resizing.
*
* @param size current size
* @return next size to allocate for internal array
*/
- protected static int nextSize(final int size) {
- if (size == 0) {
- return CHUNK_SIZE;
- }
-
- int i = size;
- while ((i & CHUNK_MASK) != 0) {
- i++;
- }
-
- return i << 1;
+ public static int nextSize(final int size) {
+ return alignUp(size + 1) * 2;
}
/**
@@ -540,7 +899,7 @@ public abstract class ArrayData {
*
* @return the next index
*/
- public long nextIndex(final long index) {
+ long nextIndex(final long index) {
return index + 1;
}
@@ -553,4 +912,53 @@ public abstract class ArrayData {
throw new RuntimeException(t);
}
}
+
+ /**
+ * Find a fast call if one exists
+ *
+ * @param clazz array data class
+ * @param desc callsite descriptor
+ * @param request link request
+ * @return fast property getter if one is found
+ */
+ public GuardedInvocation findFastCallMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
+ return null;
+ }
+
+ /**
+ * Find a fast property getter if one exists
+ *
+ * @param clazz array data class
+ * @param desc callsite descriptor
+ * @param request link request
+ * @param operator operator
+ * @return fast property getter if one is found
+ */
+ public GuardedInvocation findFastGetMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+ return null;
+ }
+
+ /**
+ * Find a fast element getter if one exists
+ *
+ * @param clazz array data class
+ * @param desc callsite descriptor
+ * @param request link request
+ * @return fast index getter if one is found
+ */
+ public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+ return null;
+ }
+
+ /**
+ * Find a fast element setter if one exists
+ *
+ * @param clazz array data class
+ * @param desc callsite descriptor
+ * @param request link request
+ * @return fast index getter if one is found
+ */
+ public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+ return null;
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
index 7a20f788..9c24a9bf 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.runtime.arrays;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -76,7 +77,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData shiftRight(final int by) {
underlying = underlying.shiftRight(by);
setLength(underlying.length());
-
return this;
}
@@ -84,7 +84,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData ensure(final long safeIndex) {
underlying = underlying.ensure(safeIndex);
setLength(underlying.length());
-
return this;
}
@@ -92,7 +91,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData shrink(final long newLength) {
underlying = underlying.shrink(newLength);
setLength(underlying.length());
-
return this;
}
@@ -100,7 +98,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData set(final int index, final Object value, final boolean strict) {
underlying = underlying.set(index, value, strict);
setLength(underlying.length());
-
return this;
}
@@ -108,7 +105,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData set(final int index, final int value, final boolean strict) {
underlying = underlying.set(index, value, strict);
setLength(underlying.length());
-
return this;
}
@@ -116,7 +112,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData set(final int index, final long value, final boolean strict) {
underlying = underlying.set(index, value, strict);
setLength(underlying.length());
-
return this;
}
@@ -124,7 +119,6 @@ abstract class ArrayFilter extends ArrayData {
public ArrayData set(final int index, final double value, final boolean strict) {
underlying = underlying.set(index, value, strict);
setLength(underlying.length());
-
return this;
}
@@ -141,21 +135,41 @@ abstract class ArrayFilter extends ArrayData {
}
@Override
+ public Type getOptimisticType() {
+ return underlying.getOptimisticType();
+ }
+
+ @Override
public int getInt(final int index) {
return underlying.getInt(index);
}
@Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return underlying.getIntOptimistic(index, programPoint);
+ }
+
+ @Override
public long getLong(final int index) {
return underlying.getLong(index);
}
@Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return underlying.getLongOptimistic(index, programPoint);
+ }
+
+ @Override
public double getDouble(final int index) {
return underlying.getDouble(index);
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return underlying.getDoubleOptimistic(index, programPoint);
+ }
+
+ @Override
public Object getObject(final int index) {
return underlying.getObject(index);
}
@@ -180,7 +194,7 @@ abstract class ArrayFilter extends ArrayData {
}
@Override
- protected ArrayData convert(final Class<?> type) {
+ public ArrayData convert(final Class<?> type) {
underlying = underlying.convert(type);
setLength(underlying.length());
return this;
@@ -190,7 +204,6 @@ abstract class ArrayFilter extends ArrayData {
public Object pop() {
final Object value = underlying.pop();
setLength(underlying.length());
-
return value;
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
index 5c857e11..f979aaa9 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
@@ -182,15 +182,15 @@ public final class ArrayIndex {
}
/**
- * Convert an index to a long value. This basically amounts to ANDing it
- * with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
+ * Convert an index to a long value. This basically amounts to converting it into a
+ * {@link JSType#toUint32(int)} uint32} as the maximum array index in JavaScript
* is 0xfffffffe
*
* @param index index to convert to long form
* @return index as uint32 in a long
*/
public static long toLongIndex(final int index) {
- return index & JSType.MAX_UINT;
+ return JSType.toUint32(index);
}
/**
@@ -201,7 +201,7 @@ public final class ArrayIndex {
* @return index as string
*/
public static String toKey(final int index) {
- return Long.toString(index & JSType.MAX_UINT);
+ return Long.toString(JSType.toUint32(index));
}
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
index 33c8679f..85f1b433 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
@@ -82,17 +82,17 @@ final class ByteBufferArrayData extends ArrayData {
}
@Override
- public void shiftLeft(int by) {
+ public void shiftLeft(final int by) {
throw unsupported("shiftLeft");
}
@Override
- public ArrayData shiftRight(int by) {
+ public ArrayData shiftRight(final int by) {
throw unsupported("shiftRight");
}
@Override
- public ArrayData ensure(long safeIndex) {
+ public ArrayData ensure(final long safeIndex) {
if (safeIndex < buf.capacity()) {
return this;
}
@@ -101,12 +101,12 @@ final class ByteBufferArrayData extends ArrayData {
}
@Override
- public ArrayData shrink(long newLength) {
+ public ArrayData shrink(final long newLength) {
throw unsupported("shrink");
}
@Override
- public ArrayData set(int index, Object value, boolean strict) {
+ public ArrayData set(final int index, final Object value, final boolean strict) {
if (value instanceof Number) {
buf.put(index, ((Number)value).byteValue());
return this;
@@ -116,45 +116,45 @@ final class ByteBufferArrayData extends ArrayData {
}
@Override
- public ArrayData set(int index, int value, boolean strict) {
+ public ArrayData set(final int index, final int value, final boolean strict) {
buf.put(index, (byte)value);
return this;
}
@Override
- public ArrayData set(int index, long value, boolean strict) {
+ public ArrayData set(final int index, final long value, final boolean strict) {
buf.put(index, (byte)value);
return this;
}
@Override
- public ArrayData set(int index, double value, boolean strict) {
+ public ArrayData set(final int index, final double value, final boolean strict) {
buf.put(index, (byte)value);
return this;
}
@Override
- public int getInt(int index) {
+ public int getInt(final int index) {
return 0x0ff & buf.get(index);
}
@Override
- public long getLong(int index) {
+ public long getLong(final int index) {
return 0x0ff & buf.get(index);
}
@Override
- public double getDouble(int index) {
+ public double getDouble(final int index) {
return 0x0ff & buf.get(index);
}
@Override
- public Object getObject(int index) {
- return (int)(0x0ff & buf.get(index));
+ public Object getObject(final int index) {
+ return 0x0ff & buf.get(index);
}
@Override
- public boolean has(int index) {
+ public boolean has(final int index) {
return index > -1 && index < buf.capacity();
}
@@ -169,12 +169,12 @@ final class ByteBufferArrayData extends ArrayData {
}
@Override
- public ArrayData delete(int index) {
+ public ArrayData delete(final int index) {
throw unsupported("delete");
}
@Override
- public ArrayData delete(long fromIndex, long toIndex) {
+ public ArrayData delete(final long fromIndex, final long toIndex) {
throw unsupported("delete");
}
@@ -189,7 +189,7 @@ final class ByteBufferArrayData extends ArrayData {
}
@Override
- public ArrayData slice(long from, long to) {
+ public ArrayData slice(final long from, final long to) {
throw unsupported("slice");
}
@@ -198,7 +198,7 @@ final class ByteBufferArrayData extends ArrayData {
throw unsupported("convert");
}
- private UnsupportedOperationException unsupported(final String method) {
+ private static UnsupportedOperationException unsupported(final String method) {
return new UnsupportedOperationException(method);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
new file mode 100644
index 00000000..2fdd184e
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
@@ -0,0 +1,364 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Interface implemented by all arrays that are directly accessible as underlying
+ * native arrays
+ */
+@Logger(name="arrays")
+public abstract class ContinuousArrayData extends ArrayData {
+ /**
+ * Constructor
+ * @param length length (elementLength)
+ */
+ protected ContinuousArrayData(final long length) {
+ super(length);
+ }
+
+ /**
+ * Check if we can put one more element at the end of this continous
+ * array without reallocating, or if we are overwriting an already
+ * allocated element
+ *
+ * @param index index to check
+ * @return true if we don't need to do any array reallocation to fit an element at index
+ */
+ public final boolean hasRoomFor(final int index) {
+ return has(index) || (index == length() && ensure(index) == this);
+ }
+
+ /**
+ * Check if an arraydata is empty
+ * @return true if empty
+ */
+ public boolean isEmpty() {
+ return length() == 0L;
+ }
+
+ /**
+ * Return element getter for a certain type at a certain program point
+ * @param returnType return type
+ * @param programPoint program point
+ * @return element getter or null if not supported (used to implement slow linkage instead
+ * as fast isn't possible)
+ */
+ public abstract MethodHandle getElementGetter(final Class<?> returnType, final int programPoint);
+
+ /**
+ * Return element getter for a certain type at a certain program point
+ * @param elementType element type
+ * @return element setter or null if not supported (used to implement slow linkage instead
+ * as fast isn't possible)
+ */
+ public abstract MethodHandle getElementSetter(final Class<?> elementType);
+
+ /**
+ * Version of has that throws a class cast exception if element does not exist
+ * used for relinking
+ *
+ * @param index index to check - currently only int indexes
+ * @return index
+ */
+ protected final int throwHas(final int index) {
+ if (!has(index)) {
+ throw new ClassCastException();
+ }
+ return index;
+ }
+
+ @Override
+ public abstract ContinuousArrayData copy();
+
+ /**
+ * Returns the type used to store an element in this array
+ * @return element type
+ */
+ public abstract Class<?> getElementType();
+
+ @Override
+ public Type getOptimisticType() {
+ return Type.typeFor(getElementType());
+ }
+
+ /**
+ * Returns the boxed type of the type used to store an element in this array
+ * @return element type
+ */
+ public abstract Class<?> getBoxedElementType();
+
+ /**
+ * Get the widest element type of two arrays. This can be done faster in subclasses, but
+ * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
+ * implemented.
+ *
+ * @param otherData another ContinuousArrayData
+ * @return the widest boxed element type
+ */
+ public ContinuousArrayData widest(final ContinuousArrayData otherData) {
+ final Class<?> elementType = getElementType();
+ return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
+ }
+
+ /**
+ * Look up a continuous array element getter
+ * @param get getter, sometimes combined with a has check that throws CCE on failure for relink
+ * @param returnType return type
+ * @param programPoint program point
+ * @return array getter
+ */
+ protected final MethodHandle getContinuousElementGetter(final MethodHandle get, final Class<?> returnType, final int programPoint) {
+ return getContinuousElementGetter(getClass(), get, returnType, programPoint);
+ }
+
+ /**
+ * Look up a continuous array element setter
+ * @param set setter, sometimes combined with a has check that throws CCE on failure for relink
+ * @param returnType return type
+ * @return array setter
+ */
+ protected final MethodHandle getContinuousElementSetter(final MethodHandle set, final Class<?> returnType) {
+ return getContinuousElementSetter(getClass(), set, returnType);
+ }
+
+ /**
+ * Return element getter for a {@link ContinuousArrayData}
+ * @param clazz clazz for exact type guard
+ * @param getHas has getter
+ * @param returnType return type
+ * @param programPoint program point
+ * @return method handle for element setter
+ */
+ protected MethodHandle getContinuousElementGetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle getHas, final Class<?> returnType, final int programPoint) {
+ final boolean isOptimistic = isValid(programPoint);
+ final int fti = getAccessorTypeIndex(getHas.type().returnType());
+ final int ti = getAccessorTypeIndex(returnType);
+ MethodHandle mh = getHas;
+
+ if (isOptimistic) {
+ if (ti < fti) {
+ mh = MH.insertArguments(ArrayData.THROW_UNWARRANTED.methodHandle(), 1, programPoint);
+ }
+ }
+ mh = MH.asType(mh, mh.type().changeReturnType(returnType).changeParameterType(0, clazz));
+
+ if (!isOptimistic) {
+ //for example a & array[17];
+ return Lookup.filterReturnType(mh, returnType);
+ }
+ return mh;
+ }
+
+ /**
+ * Return element setter for a {@link ContinuousArrayData}
+ * @param clazz clazz for exact type guard
+ * @param setHas set has guard
+ * @param elementType element type
+ * @return method handle for element setter
+ */
+ protected MethodHandle getContinuousElementSetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle setHas, final Class<?> elementType) {
+ return MH.asType(setHas, setHas.type().changeParameterType(2, elementType).changeParameterType(0, clazz));
+ }
+
+ /** Fast access guard - it is impractical for JIT performance reasons to use only CCE asType as guard :-(, also we need
+ the null case explicitly, which is the one that CCE doesn't handle */
+ protected static final MethodHandle FAST_ACCESS_GUARD =
+ MH.dropArguments(
+ staticCall(
+ MethodHandles.lookup(),
+ ContinuousArrayData.class,
+ "guard",
+ boolean.class,
+ Class.class,
+ ScriptObject.class).methodHandle(),
+ 2,
+ int.class);
+
+ @SuppressWarnings("unused")
+ private static final boolean guard(final Class<? extends ContinuousArrayData> clazz, final ScriptObject sobj) {
+ if (sobj != null && sobj.getArray().getClass() == clazz) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return a fast linked array getter, or null if we have to dispatch to super class
+ * @param desc descriptor
+ * @param request link request
+ * @return invocation or null if needs to be sent to slow relink
+ */
+ @Override
+ public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
+ final MethodType callType = desc.getMethodType();
+ final Class<?> indexType = callType.parameterType(1);
+ final Class<?> returnType = callType.returnType();
+
+ if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
+ final Object[] args = request.getArguments();
+ final int index = (int)args[args.length - 1];
+
+ if (has(index)) {
+ final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
+ final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+ MethodHandle getElement = getElementGetter(returnType, programPoint);
+ if (getElement != null) {
+ getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz)));
+ final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
+ return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Return a fast linked array setter, or null if we have to dispatch to super class
+ * @param desc descriptor
+ * @param request link request
+ * @return invocation or null if needs to be sent to slow relink
+ */
+ @Override
+ public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+ final MethodType callType = desc.getMethodType();
+ final Class<?> indexType = callType.parameterType(1);
+ final Class<?> elementType = callType.parameterType(2);
+
+ if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
+ final Object[] args = request.getArguments();
+ final int index = (int)args[args.length - 2];
+
+ if (hasRoomFor(index)) {
+ MethodHandle setElement = getElementSetter(elementType); //Z(continuousarraydata, int, int), return true if successful
+ if (setElement != null) {
+ //else we are dealing with a wider type than supported by this callsite
+ MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
+ getArray = MH.asType(getArray, getArray.type().changeReturnType(getClass()));
+ setElement = MH.filterArguments(setElement, 0, getArray);
+ final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
+ return new GuardedInvocation(setElement, guard, (SwitchPoint)null, ClassCastException.class); //CCE if not a scriptObject anymore
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Specialization - fast push implementation
+ * @param arg argument
+ * @return new array length
+ */
+ public long fastPush(final int arg) {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast push implementation
+ * @param arg argument
+ * @return new array length
+ */
+ public long fastPush(final long arg) {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast push implementation
+ * @param arg argument
+ * @return new array length
+ */
+ public long fastPush(final double arg) {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast push implementation
+ * @param arg argument
+ * @return new array length
+ */
+ public long fastPush(final Object arg) {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast pop implementation
+ * @return element value
+ */
+ public int fastPopInt() {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast pop implementation
+ * @return element value
+ */
+ public long fastPopLong() {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast pop implementation
+ * @return element value
+ */
+ public double fastPopDouble() {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast pop implementation
+ * @return element value
+ */
+ public Object fastPopObject() {
+ throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
+ }
+
+ /**
+ * Specialization - fast concat implementation
+ * @param otherData data to concat
+ * @return new arraydata
+ */
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ throw new ClassCastException(String.valueOf(getClass()) + " != " + String.valueOf(otherData.getClass()));
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
index 20c415e7..4fa89f7d 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
import java.lang.reflect.Array;
import jdk.nashorn.internal.runtime.BitVector;
@@ -39,13 +38,12 @@ final class DeletedArrayFilter extends ArrayFilter {
DeletedArrayFilter(final ArrayData underlying) {
super(underlying);
-
this.deleted = new BitVector(underlying.length());
}
@Override
public ArrayData copy() {
- DeletedArrayFilter copy = new DeletedArrayFilter(underlying.copy());
+ final DeletedArrayFilter copy = new DeletedArrayFilter(underlying.copy());
copy.getDeleted().copy(deleted);
return copy;
}
@@ -87,7 +85,6 @@ final class DeletedArrayFilter extends ArrayFilter {
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
deleted.shiftRight(by, length());
-
return this;
}
@@ -107,35 +104,30 @@ final class DeletedArrayFilter extends ArrayFilter {
public ArrayData shrink(final long newLength) {
super.shrink(newLength);
deleted.resize(length());
-
return this;
}
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
index 40368966..953b9213 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
@@ -36,17 +36,25 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
private long lo, hi;
DeletedRangeArrayFilter(final ArrayData underlying, final long lo, final long hi) {
- super(underlying);
+ super(maybeSparse(underlying, hi));
this.lo = lo;
this.hi = hi;
}
+ private static ArrayData maybeSparse(final ArrayData underlying, final long hi) {
+ if (hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
+ return underlying;
+ }
+ return new SparseArrayData(underlying, underlying.length());
+ }
+
private boolean isEmpty() {
return lo > hi;
}
private boolean isDeleted(final int index) {
- return lo <= index && index <= hi;
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ return lo <= longIndex && longIndex <= hi;
}
@Override
@@ -58,9 +66,9 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
public Object[] asObjectArray() {
final Object[] value = super.asObjectArray();
- if (lo <= Integer.MAX_VALUE) {
- final int intHi = (int)Math.min(hi, Integer.MAX_VALUE);
- for (int i = (int)lo; i <= intHi; i++) {
+ if (lo < Integer.MAX_VALUE) {
+ final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE);
+ for (int i = (int)lo; i < end; i++) {
value[i] = ScriptRuntime.UNDEFINED;
}
}
@@ -73,9 +81,9 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
final Object value = super.asArrayOfType(componentType);
final Object undefValue = convertUndefinedValue(componentType);
- if (lo <= Integer.MAX_VALUE) {
- final int intHi = (int)Math.min(hi, Integer.MAX_VALUE);
- for (int i = (int)lo; i <= intHi; i++) {
+ if (lo < Integer.MAX_VALUE) {
+ final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE);
+ for (int i = (int)lo; i < end; i++) {
Array.set(value, i, undefValue);
}
}
@@ -102,8 +110,9 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
@Override
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
- lo = Math.min(length(), lo + by);
- hi = Math.min(length() - 1, hi + by);
+ final long len = length();
+ lo = Math.min(len, lo + by);
+ hi = Math.min(len - 1, hi + by);
return isEmpty() ? getUnderlying() : this;
}
@@ -229,7 +238,7 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
@Override
public Object pop() {
- final int index = (int)(length() - 1);
+ final int index = (int)length() - 1;
if (super.has(index)) {
final boolean isDeleted = isDeleted(index);
final Object value = super.pop();
diff --git a/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
index e15541db..1e71b44d 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
@@ -25,10 +25,10 @@
package jdk.nashorn.internal.runtime.arrays;
-import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
* ArrayData after the array has been frozen by Object.freeze call.
@@ -79,4 +79,15 @@ final class FrozenArrayFilter extends SealedArrayFilter {
}
return this;
}
+
+ @Override
+ public ArrayData push(final boolean strict, final Object... items) {
+ return this; //nop
+ }
+
+ @Override
+ public Object pop() {
+ final int len = (int)underlying.length();
+ return len == 0 ? ScriptRuntime.UNDEFINED : underlying.getObject(len - 1);
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
index 07ddda2d..381390ce 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -33,7 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* Implementation of {@link ArrayData} as soon as an int has been
* written to the array. This is the default data for new arrays
*/
-final class IntArrayData extends ArrayData {
+final class IntArrayData extends ContinuousArrayData implements IntElements {
/**
* The wrapped array
*/
@@ -53,75 +56,140 @@ final class IntArrayData extends ArrayData {
* @param array an int array
* @param length a length, not necessarily array.length
*/
- IntArrayData(final int array[], final int length) {
+ IntArrayData(final int[] array, final int length) {
super(length);
- assert array.length >= length;
+ assert array == null || array.length >= length;
this.array = array;
}
@Override
- public ArrayData copy() {
- return new IntArrayData(array.clone(), (int) length());
+ public final Class<?> getElementType() {
+ return int.class;
}
@Override
+ public final Class<?> getBoxedElementType() {
+ return Integer.class;
+ }
+
+ @Override
+ public final int getElementWeight() {
+ return 1;
+ }
+
+ @Override
+ public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
+ return otherData;
+ }
+
+ private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ @Override
public Object[] asObjectArray() {
- return toObjectArray(array, (int) length());
+ return toObjectArray(true);
+ }
+
+ @SuppressWarnings("unused")
+ private int getElem(final int index) {
+ if (has(index)) {
+ return array[index];
+ }
+ throw new ClassCastException();
+ }
+
+ @SuppressWarnings("unused")
+ private void setElem(final int index, final int elem) {
+ if (hasRoomFor(index)) {
+ array[index] = elem;
+ return;
+ }
+ throw new ClassCastException();
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return elementType == int.class ? getContinuousElementSetter(SET_ELEM, elementType) : null;
+ }
+
+ @Override
+ public IntArrayData copy() {
+ return new IntArrayData(array.clone(), (int)length());
}
@Override
public Object asArrayOfType(final Class<?> componentType) {
- if(componentType == int.class) {
- return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+ if (componentType == int.class) {
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
- private static Object[] toObjectArray(final int[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[array.length];
+ private Object[] toObjectArray(final boolean trim) {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Integer.valueOf(array[index]);
}
return oarray;
}
- private static double[] toDoubleArray(final int[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
+ private double[] toDoubleArray() {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final double[] darray = new double[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
darray[index] = array[index];
}
return darray;
}
- private static long[] toLongArray(final int[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
+ private long[] toLongArray() {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final long[] larray = new long[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
larray[index] = array[index];
}
return larray;
}
+ private LongArrayData convertToLong() {
+ return new LongArrayData(toLongArray(), (int)length());
+ }
+
+ private NumberArrayData convertToDouble() {
+ return new NumberArrayData(toDoubleArray(), (int)length());
+ }
+
+ private ObjectArrayData convertToObject() {
+ return new ObjectArrayData(toObjectArray(false), (int)length());
+ }
+
@Override
public ArrayData convert(final Class<?> type) {
if (type == Integer.class) {
return this;
- }
- final int length = (int) length();
- if (type == Long.class) {
- return new LongArrayData(IntArrayData.toLongArray(array, length), length);
+ } else if (type == Long.class) {
+ return convertToLong();
} else if (type == Double.class) {
- return new NumberArrayData(IntArrayData.toDoubleArray(array, length), length);
+ return convertToDouble();
} else {
- return new ObjectArrayData(IntArrayData.toObjectArray(array, length), length);
+ assert type == null || (!Number.class.isAssignableFrom(type) && !type.isPrimitive());
+ return convertToObject();
}
}
@@ -144,36 +212,28 @@ final class IntArrayData extends ArrayData {
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(this, safeIndex + 1);
}
-
- int newLength = array.length;
-
- while (newLength <= safeIndex) {
- newLength = ArrayData.nextSize(newLength);
- }
-
- if (array.length <= safeIndex) {
+ final int alen = array.length;
+ if (safeIndex >= alen) {
+ final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength);
}
-
setLength(safeIndex + 1);
-
return this;
}
@Override
public ArrayData shrink(final long newLength) {
- Arrays.fill(array, (int) newLength, array.length, 0);
-
+ Arrays.fill(array, (int)newLength, array.length, 0);
return this;
}
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
- if (value instanceof Integer) {
- return set(index, ((Number)value).intValue(), strict);
+ if (JSType.isRepresentableAsInt(value)) {
+ return set(index, JSType.toInt32(value), strict);
} else if (value == ScriptRuntime.UNDEFINED) {
return new UndefinedArrayFilter(this).set(index, value, strict);
}
@@ -192,9 +252,8 @@ final class IntArrayData extends ArrayData {
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
- final int intValue = (int)value;
- if (intValue == value) {
- array[index] = intValue;
+ if (JSType.isRepresentableAsInt(value)) {
+ array[index] = JSType.toInt32(value);
setLength(Math.max(index + 1, length()));
return this;
}
@@ -219,16 +278,31 @@ final class IntArrayData extends ArrayData {
}
@Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public long getLong(final int index) {
return array[index];
}
@Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public double getDouble(final int index) {
return array[index];
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public Object getObject(final int index) {
return array[index];
}
@@ -250,11 +324,12 @@ final class IntArrayData extends ArrayData {
@Override
public Object pop() {
- if (length() == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int) length() - 1;
+ final int newLength = len - 1;
final int elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -264,10 +339,18 @@ final class IntArrayData extends ArrayData {
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? (from + length()) : from;
- final long newLength = to - start;
+ return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from)));
+ }
- return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
+ @Override
+ public final ArrayData push(final boolean strict, final int item) {
+ final long len = length();
+ final ArrayData newData = ensure(len);
+ if (newData == this) {
+ array[(int)len] = item;
+ return this;
+ }
+ return newData.set((int)len, item, strict);
}
@Override
@@ -277,8 +360,14 @@ final class IntArrayData extends ArrayData {
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
}
- final ArrayData returnValue = (removed == 0) ?
- EMPTY_ARRAY : new IntArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
+ final ArrayData returnValue = removed == 0 ?
+ EMPTY_ARRAY :
+ new IntArrayData(
+ Arrays.copyOfRange(
+ array,
+ start,
+ start + removed),
+ removed);
if (newLength != oldLength) {
final int[] newArray;
@@ -297,4 +386,63 @@ final class IntArrayData extends ArrayData {
return returnValue;
}
+
+ @Override
+ public long fastPush(final int arg) {
+ final int len = (int)length();
+ if (len == array.length) {
+ array = Arrays.copyOf(array, nextSize(len));
+ }
+ array[len] = arg;
+ return increaseLength();
+ }
+
+ //length must not be zero
+ @Override
+ public int fastPopInt() {
+ if (length() == 0) {
+ throw new ClassCastException(); //relink
+ }
+ final int newLength = (int)decreaseLength();
+ final int elem = array[newLength];
+ array[newLength] = 0;
+ return elem;
+ }
+
+ @Override
+ public long fastPopLong() {
+ return fastPopInt();
+ }
+
+ @Override
+ public double fastPopDouble() {
+ return fastPopInt();
+ }
+
+ @Override
+ public Object fastPopObject() {
+ return fastPopInt();
+ }
+
+ @Override
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
+ assert otherLength > 0 && thisLength > 0;
+
+ final int[] otherArray = ((IntArrayData)otherData).array;
+ final int newLength = otherLength + thisLength;
+ final int[] newArray = new int[ArrayData.alignUp(newLength)];
+
+ System.arraycopy(array, 0, newArray, 0, thisLength);
+ System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
+
+ return new IntArrayData(newArray, newLength);
+ }
+
+ @Override
+ public String toString() {
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IntElements.java b/src/jdk/nashorn/internal/runtime/arrays/IntElements.java
new file mode 100644
index 00000000..5bd26843
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/IntElements.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.arrays;
+
+/**
+ * Marker interface for any ContinuousArray with int elements
+ * Used for type checks that throw ClassCastExceptions and force relinks
+ * for fast NativeArray specializations of builtin methods
+ */
+public interface IntElements extends IntOrLongElements {
+ //empty
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java b/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java
new file mode 100644
index 00000000..f176d757
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.arrays;
+
+/**
+ * Marker interface for any ContinuousArray with int or long elements
+ * Used for type checks that throw ClassCastExceptions and force relinks
+ * for fast NativeArray specializations of builtin methods
+ */
+public interface IntOrLongElements extends NumericElements {
+ //empty
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
index 244739b3..ff4c13e2 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
@@ -25,11 +25,7 @@
package jdk.nashorn.internal.runtime.arrays;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
-import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -98,17 +94,7 @@ public abstract class IteratorAction<T> {
* @return result of apply
*/
public final T apply() {
- final boolean strict;
- if (callbackfn instanceof ScriptFunction) {
- strict = ((ScriptFunction)callbackfn).isStrict();
- } else if (callbackfn instanceof JSObject &&
- ((JSObject)callbackfn).isFunction()) {
- strict = ((JSObject)callbackfn).isStrictFunction();
- } else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) {
- strict = false;
- } else {
- throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
- }
+ final boolean strict = Bootstrap.isStrictCallable(callbackfn);
// for non-strict callback, need to translate undefined thisArg to be global object
thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
diff --git a/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java b/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java
new file mode 100644
index 00000000..945d80d2
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java
@@ -0,0 +1,198 @@
+package jdk.nashorn.internal.runtime.arrays;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Filter to use for ArrayData where the length is not writable.
+ * The default behavior is just to ignore {@link ArrayData#setLength}
+ */
+final class LengthNotWritableFilter extends ArrayFilter {
+ private final SortedMap<Long, Object> extraElements; //elements with index >= length
+
+ /**
+ * Constructor
+ * @param underlying array
+ */
+ LengthNotWritableFilter(final ArrayData underlying) {
+ this(underlying, new TreeMap<Long, Object>());
+ }
+
+ private LengthNotWritableFilter(final ArrayData underlying, final SortedMap<Long, Object> extraElements) {
+ super(underlying);
+ this.extraElements = extraElements;
+ }
+
+ @Override
+ public ArrayData copy() {
+ return new LengthNotWritableFilter(underlying.copy(), new TreeMap<>(extraElements));
+ }
+
+ @Override
+ public boolean has(final int index) {
+ return super.has(index) || extraElements.containsKey((long)index);
+ }
+
+ /**
+ * Set the length of the data array
+ *
+ * @param length the new length for the data array
+ */
+ @Override
+ public void setLength(final long length) {
+ //empty - setting length for a LengthNotWritableFilter is always a nop
+ }
+
+ @Override
+ public ArrayData ensure(final long index) {
+ return this;
+ }
+
+ @Override
+ public ArrayData slice(final long from, final long to) {
+ //return array[from...to), or array[from...length] if undefined, in this case not as we are an ArrayData
+ return new LengthNotWritableFilter(underlying.slice(from, to), extraElements.subMap(from, to));
+ }
+
+ private boolean checkAdd(final long index, final Object value) {
+ if (index >= length()) {
+ extraElements.put(index, value);
+ return true;
+ }
+ return false;
+ }
+
+ private Object get(final long index) {
+ final Object obj = extraElements.get(index);
+ if (obj == null) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ return obj;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ if (index >= length()) {
+ return JSType.toInt32(get(index));
+ }
+ return underlying.getInt(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toInt32Optimistic(get(index), programPoint);
+ }
+ return underlying.getIntOptimistic(index, programPoint);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ if (index >= length()) {
+ return JSType.toLong(get(index));
+ }
+ return underlying.getLong(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toLongOptimistic(get(index), programPoint);
+ }
+ return underlying.getLongOptimistic(index, programPoint);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ if (index >= length()) {
+ return JSType.toNumber(get(index));
+ }
+ return underlying.getDouble(index);
+ }
+
+ @Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toNumberOptimistic(get(index), programPoint);
+ }
+ return underlying.getDoubleOptimistic(index, programPoint);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ if (index >= length()) {
+ return get(index);
+ }
+ return underlying.getObject(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData delete(final int index) {
+ extraElements.remove(index);
+ underlying = underlying.delete(index);
+ return this;
+ }
+
+ @Override
+ public ArrayData delete(final long fromIndex, final long toIndex) {
+ for (final Iterator<Long> iter = extraElements.keySet().iterator(); iter.hasNext();) {
+ final long next = iter.next();
+ if (next >= fromIndex && next <= toIndex) {
+ iter.remove();
+ }
+ if (next > toIndex) { //ordering guaranteed because TreeSet
+ break;
+ }
+ }
+ underlying = underlying.delete(fromIndex, toIndex);
+ return this;
+ }
+
+ @Override
+ public Iterator<Long> indexIterator() {
+ final List<Long> keys = computeIteratorKeys();
+ keys.addAll(extraElements.keySet()); //even if they are outside length this is fine
+ return keys.iterator();
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
index 4bb96aae..0437cdfe 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
@@ -25,6 +25,10 @@
package jdk.nashorn.internal.runtime.arrays;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -33,7 +37,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* Implementation of {@link ArrayData} as soon as a long has been
* written to the array
*/
-final class LongArrayData extends ArrayData {
+final class LongArrayData extends ContinuousArrayData implements IntOrLongElements {
/**
* The wrapped array
*/
@@ -47,24 +51,45 @@ final class LongArrayData extends ArrayData {
LongArrayData(final long array[], final int length) {
super(length);
assert array.length >= length;
- this.array = array;
+ this.array = array;
}
@Override
- public ArrayData copy() {
- return new LongArrayData(array.clone(), (int) length());
+ public final Class<?> getElementType() {
+ return long.class;
+ }
+
+ @Override
+ public final Class<?> getBoxedElementType() {
+ return Long.class;
+ }
+
+ @Override
+ public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
+ return otherData instanceof IntElements ? this : otherData;
+ }
+
+ @Override
+ public final int getElementWeight() {
+ return 2;
+ }
+
+ @Override
+ public LongArrayData copy() {
+ return new LongArrayData(array.clone(), (int)length());
}
@Override
public Object[] asObjectArray() {
- return toObjectArray(array, (int) length());
+ return toObjectArray(true);
}
- private static Object[] toObjectArray(final long[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[array.length];
+ private Object[] toObjectArray(final boolean trim) {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Long.valueOf(array[index]);
}
@@ -73,17 +98,19 @@ final class LongArrayData extends ArrayData {
@Override
public Object asArrayOfType(final Class<?> componentType) {
- if(componentType == long.class) {
- return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+ if (componentType == long.class) {
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
- private static double[] toDoubleArray(final long[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
+ private double[] toDoubleArray() {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final double[] darray = new double[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
darray[index] = array[index];
}
@@ -91,15 +118,15 @@ final class LongArrayData extends ArrayData {
}
@Override
- public ArrayData convert(final Class<?> type) {
+ public ContinuousArrayData convert(final Class<?> type) {
if (type == Integer.class || type == Long.class) {
return this;
}
- final int length = (int) length();
+ final int len = (int)length();
if (type == Double.class) {
- return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length);
+ return new NumberArrayData(toDoubleArray(), len);
}
- return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length);
+ return new ObjectArrayData(toObjectArray(false), len);
}
@Override
@@ -121,29 +148,21 @@ final class LongArrayData extends ArrayData {
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(this, safeIndex + 1);
}
-
- int newLength = array.length;
-
- while (newLength <= safeIndex) {
- newLength = ArrayData.nextSize(newLength);
- }
-
- if (array.length <= safeIndex) {
+ final int alen = array.length;
+ if (safeIndex >= alen) {
+ final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength);
}
-
setLength(safeIndex + 1);
-
return this;
}
@Override
public ArrayData shrink(final long newLength) {
- Arrays.fill(array, (int) newLength, array.length, 0);
-
+ Arrays.fill(array, (int)newLength, array.length, 0L);
return this;
}
@@ -183,6 +202,39 @@ final class LongArrayData extends ArrayData {
return convert(Double.class).set(index, value, strict);
}
+ private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
+
+ @SuppressWarnings("unused")
+ private long getElem(final int index) {
+ if (has(index)) {
+ return array[index];
+ }
+ throw new ClassCastException();
+ }
+
+ @SuppressWarnings("unused")
+ private void setElem(final int index, final long elem) {
+ if (hasRoomFor(index)) {
+ array[index] = elem;
+ return;
+ }
+ throw new ClassCastException();
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class) {
+ return null;
+ }
+ return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return elementType == int.class || elementType == long.class ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
+ }
+
@Override
public int getInt(final int index) {
return (int)array[index];
@@ -194,11 +246,21 @@ final class LongArrayData extends ArrayData {
}
@Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public double getDouble(final int index) {
return array[index];
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public Object getObject(final int index) {
return array[index];
}
@@ -220,11 +282,12 @@ final class LongArrayData extends ArrayData {
@Override
public Object pop() {
- if (length() == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int) (length() - 1);
+ final int newLength = len - 1;
final long elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -234,19 +297,30 @@ final class LongArrayData extends ArrayData {
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? (from + length()) : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
+ public final ArrayData push(final boolean strict, final long item) {
+ final long len = length();
+ final ArrayData newData = ensure(len);
+ if (newData == this) {
+ array[(int)len] = item;
+ return this;
+ }
+ return newData.set((int)len, item, strict);
+ }
+
+ @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
}
- final ArrayData returnValue = (removed == 0) ?
+ final ArrayData returnValue = removed == 0 ?
EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
if (newLength != oldLength) {
@@ -266,4 +340,74 @@ final class LongArrayData extends ArrayData {
return returnValue;
}
+
+ @Override
+ public long fastPush(final int arg) {
+ return fastPush((long)arg);
+ }
+
+ @Override
+ public long fastPush(final long arg) {
+ final int len = (int)length();
+ if (len == array.length) {
+ array = Arrays.copyOf(array, nextSize(len));
+ }
+ array[len] = arg;
+ return increaseLength();
+ }
+
+ @Override
+ public long fastPopLong() {
+ if (length() == 0) {
+ throw new ClassCastException(); //undefined result
+ }
+ final int newLength = (int)decreaseLength();
+ final long elem = array[newLength];
+ array[newLength] = 0;
+ return elem;
+ }
+
+ @Override
+ public double fastPopDouble() {
+ return fastPopLong();
+ }
+
+ @Override
+ public Object fastPopObject() {
+ return fastPopLong();
+ }
+
+ @Override
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
+ assert otherLength > 0 && thisLength > 0;
+
+ final long[] otherArray = ((LongArrayData)otherData).array;
+ final int newLength = otherLength + thisLength;
+ final long[] newArray = new long[ArrayData.alignUp(newLength)];
+
+ System.arraycopy(array, 0, newArray, 0, thisLength);
+ System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
+
+ return new LongArrayData(newArray, newLength);
+ }
+
+ @Override
+ public String toString() {
+ assert length() <= array.length : length() + " > " + array.length;
+
+ final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
+ append(": [");
+ final int len = (int)length();
+ for (int i = 0; i < len; i++) {
+ sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
+ if (i + 1 < len) {
+ sb.append(", ");
+ }
+ }
+ sb.append(']');
+
+ return sb.toString();
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
deleted file mode 100644
index 1f2298c0..00000000
--- a/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.arrays;
-
-import java.lang.reflect.Array;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-
-/**
- * Place holding array data for non-array objects. Activates a true array when
- * accessed. Should only exist as a singleton defined in ArrayData.
- */
-final class NoTypeArrayData extends ArrayData {
- NoTypeArrayData() {
- super(0);
- }
-
- NoTypeArrayData(final long length) {
- super(length);
- }
-
- @Override
- public Object[] asObjectArray() {
- return new Object[0];
- }
-
- @Override
- public ArrayData copy() {
- return new NoTypeArrayData();
- }
-
- @Override
- public Object asArrayOfType(final Class<?> componentType) {
- return Array.newInstance(componentType, 0);
- }
-
- @Override
- public ArrayData convert(final Class<?> type) {
- final long length = length();
- final ArrayData arrayData;
- if (type == Long.class) {
- arrayData = new LongArrayData(new long[ArrayData.nextSize((int)length)], (int)length);
- } else if (type == Double.class) {
- arrayData = new NumberArrayData(new double[ArrayData.nextSize((int)length)], (int)length);
- } else if (type == Integer.class) {
- arrayData = new IntArrayData(new int[ArrayData.nextSize((int)length)], (int)length);
- } else {
- assert !type.isPrimitive();
- arrayData = new ObjectArrayData(new Object[ArrayData.nextSize((int)length)], (int)length);
- }
- return length == 0 ? arrayData : new DeletedRangeArrayFilter(arrayData, 0, length - 1);
- }
-
- @Override
- public void shiftLeft(final int by) {
- //empty
- }
-
- @Override
- public ArrayData shiftRight(final int by) {
- return this;
- }
-
- @Override
- public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
- return new SparseArrayData(this, safeIndex + 1);
- }
-
- // Don't trample the shared EMPTY_ARRAY.
- if (length() == 0) {
- return new NoTypeArrayData(Math.max(safeIndex + 1, length()));
- }
-
- setLength(Math.max(safeIndex + 1, length()));
- return this;
- }
-
- @Override
- public ArrayData shrink(final long newLength) {
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final Object value, final boolean strict) {
- ArrayData newData;
-
- if (value instanceof Double) {
- newData = convert(Double.class);
- } else if (value instanceof Long) {
- newData = convert(Long.class);
- } else if (value instanceof Integer) {
- newData = convert(Integer.class);
- } else {
- assert !(value instanceof Number);
- newData = convert(value == null ? Object.class : value.getClass());
- }
-
- return newData.set(index, value, strict);
- }
-
- @Override
- public ArrayData set(final int index, final int value, final boolean strict) {
- final ArrayData newData = convert(Integer.class);
- return newData.set(index, value, strict);
- }
-
- @Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- final ArrayData newData = convert(Long.class);
- return newData.set(index, value, strict);
- }
-
- @Override
- public ArrayData set(final int index, final double value, final boolean strict) {
- final ArrayData newData = convert(Double.class);
- return newData.set(index, value, strict);
- }
-
- @Override
- public int getInt(final int index) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
-
- @Override
- public long getLong(final int index) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
-
- @Override
- public double getDouble(final int index) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
-
- @Override
- public Object getObject(final int index) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
-
- @Override
- public boolean has(final int index) {
- return false;
- }
-
- @Override
- public ArrayData delete(final int index) {
- return new DeletedRangeArrayFilter(this, index, index);
- }
-
- @Override
- public ArrayData delete(final long fromIndex, final long toIndex) {
- return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
- }
-
- @Override
- public Object pop() {
- return ScriptRuntime.UNDEFINED;
- }
-
- @Override
- public ArrayData slice(final long from, final long to) {
- return this;
- }
-}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java
new file mode 100644
index 00000000..7e0f3c63
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java
@@ -0,0 +1,68 @@
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Filter class that wrap arrays that have been tagged non extensible
+ */
+final class NonExtensibleArrayFilter extends ArrayFilter {
+
+ /**
+ * Constructor
+ * @param underlying array
+ */
+ NonExtensibleArrayFilter(final ArrayData underlying) {
+ super(underlying);
+ }
+
+ @Override
+ public ArrayData copy() {
+ return new NonExtensibleArrayFilter(underlying.copy());
+ }
+
+ @Override
+ public ArrayData slice(final long from, final long to) {
+ return new NonExtensibleArrayFilter(underlying.slice(from, to));
+ }
+
+ private ArrayData extensionCheck(final boolean strict, final int index) {
+ if (!strict) {
+ return this;
+ }
+ throw typeError(Global.instance(), "object.non.extensible", String.valueOf(index), ScriptRuntime.safeToString(this));
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ if (has(index)) {
+ return underlying.set(index, value, strict);
+ }
+ return extensionCheck(strict, index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ if (has(index)) {
+ return underlying.set(index, value, strict);
+ }
+ return extensionCheck(strict, index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ if (has(index)) {
+ return underlying.set(index, value, strict);
+ }
+ return extensionCheck(strict, index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ if (has(index)) {
+ return underlying.set(index, value, strict);
+ }
+ return extensionCheck(strict, index);
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
index 8254db63..2522b979 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
@@ -25,15 +25,18 @@
package jdk.nashorn.internal.runtime.arrays;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.Arrays;
/**
* Implementation of {@link ArrayData} as soon as a double has been
* written to the array
*/
-final class NumberArrayData extends ArrayData {
+final class NumberArrayData extends ContinuousArrayData implements NumericElements {
/**
* The wrapped array
*/
@@ -44,27 +47,48 @@ final class NumberArrayData extends ArrayData {
* @param array an int array
* @param length a length, not necessarily array.length
*/
- NumberArrayData(final double array[], final int length) {
+ NumberArrayData(final double[] array, final int length) {
super(length);
assert array.length >= length;
- this.array = array;
+ this.array = array;
+ }
+
+ @Override
+ public final Class<?> getElementType() {
+ return double.class;
+ }
+
+ @Override
+ public final Class<?> getBoxedElementType() {
+ return Double.class;
+ }
+
+ @Override
+ public final int getElementWeight() {
+ return 3;
}
@Override
- public ArrayData copy() {
- return new NumberArrayData(array.clone(), (int) length());
+ public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
+ return otherData instanceof IntOrLongElements ? this : otherData;
+ }
+
+ @Override
+ public NumberArrayData copy() {
+ return new NumberArrayData(array.clone(), (int)length());
}
@Override
public Object[] asObjectArray() {
- return toObjectArray(array, (int) length());
+ return toObjectArray(true);
}
- private static Object[] toObjectArray(final double[] array, final int length) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[array.length];
+ private Object[] toObjectArray(final boolean trim) {
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Double.valueOf(array[index]);
}
return oarray;
@@ -72,17 +96,18 @@ final class NumberArrayData extends ArrayData {
@Override
public Object asArrayOfType(final Class<?> componentType) {
- if(componentType == double.class) {
- return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+ if (componentType == double.class) {
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
@Override
- public ArrayData convert(final Class<?> type) {
+ public ContinuousArrayData convert(final Class<?> type) {
if (type != Double.class && type != Integer.class && type != Long.class) {
- final int length = (int) length();
- return new ObjectArrayData(NumberArrayData.toObjectArray(array, length), length);
+ final int len = (int)length();
+ return new ObjectArrayData(toObjectArray(false), len);
}
return this;
}
@@ -105,29 +130,22 @@ final class NumberArrayData extends ArrayData {
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(this, safeIndex + 1);
}
-
- int newLength = array.length;
-
- while (newLength <= safeIndex) {
- newLength = ArrayData.nextSize(newLength);
+ final int alen = array.length;
+ if (safeIndex >= alen) {
+ final int newLength = ArrayData.nextSize((int)safeIndex);
+ array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed?
}
-
- if (array.length <= safeIndex) {
- array = Arrays.copyOf(array, newLength);
- Arrays.fill(array, (int) length(), newLength, Double.NaN);
- }
-
setLength(safeIndex + 1);
-
return this;
+
}
@Override
public ArrayData shrink(final long newLength) {
- Arrays.fill(array, (int) newLength, array.length, 0.0);
+ Arrays.fill(array, (int)newLength, array.length, 0.0);
return this;
}
@@ -164,6 +182,39 @@ final class NumberArrayData extends ArrayData {
return this;
}
+ private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+ @SuppressWarnings("unused")
+ private double getElem(final int index) {
+ if (has(index)) {
+ return array[index];
+ }
+ throw new ClassCastException();
+ }
+
+ @SuppressWarnings("unused")
+ private void setElem(final int index, final double elem) {
+ if (hasRoomFor(index)) {
+ array[index] = elem;
+ return;
+ }
+ throw new ClassCastException();
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class || returnType == long.class) {
+ return null;
+ }
+ return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return elementType.isPrimitive() ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
+ }
+
@Override
public int getInt(final int index) {
return (int)array[index];
@@ -180,6 +231,11 @@ final class NumberArrayData extends ArrayData {
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ return array[index];
+ }
+
+ @Override
public Object getObject(final int index) {
return array[index];
}
@@ -201,11 +257,12 @@ final class NumberArrayData extends ArrayData {
@Override
public Object pop() {
- if (length() == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return UNDEFINED;
}
- final int newLength = (int) (length() - 1);
+ final int newLength = len - 1;
final double elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -214,19 +271,30 @@ final class NumberArrayData extends ArrayData {
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? (from + length()) : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
+ public final ArrayData push(final boolean strict, final double item) {
+ final long len = length();
+ final ArrayData newData = ensure(len);
+ if (newData == this) {
+ array[(int)len] = item;
+ return this;
+ }
+ return newData.set((int)len, item, strict);
+ }
+
+ @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
}
- final ArrayData returnValue = (removed == 0) ?
+ final ArrayData returnValue = removed == 0 ?
EMPTY_ARRAY : new NumberArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
if (newLength != oldLength) {
@@ -246,4 +314,63 @@ final class NumberArrayData extends ArrayData {
return returnValue;
}
+
+ @Override
+ public long fastPush(final int arg) {
+ return fastPush((double)arg);
+ }
+
+ @Override
+ public long fastPush(final long arg) {
+ return fastPush((double)arg);
+ }
+
+ @Override
+ public long fastPush(final double arg) {
+ final int len = (int)length();
+ if (len == array.length) {
+ //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory
+ array = Arrays.copyOf(array, nextSize(len));
+ }
+ array[len] = arg;
+ return increaseLength();
+ }
+
+ @Override
+ public double fastPopDouble() {
+ if (length() == 0) {
+ throw new ClassCastException();
+ }
+ final int newLength = (int)decreaseLength();
+ final double elem = array[newLength];
+ array[newLength] = 0;
+ return elem;
+ }
+
+ @Override
+ public Object fastPopObject() {
+ return fastPopDouble();
+ }
+
+ @Override
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
+ assert otherLength > 0 && thisLength > 0;
+
+ final double[] otherArray = ((NumberArrayData)otherData).array;
+ final int newLength = otherLength + thisLength;
+ final double[] newArray = new double[ArrayData.alignUp(newLength)];
+
+ System.arraycopy(array, 0, newArray, 0, thisLength);
+ System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
+
+ return new NumberArrayData(newArray, newLength);
+ }
+
+ @Override
+ public String toString() {
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java b/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java
new file mode 100644
index 00000000..cb87ea91
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.arrays;
+
+/**
+ * Marker interface for any ContinuousArray with numeric elements
+ * (int, long or double)
+ * Used for type checks that throw ClassCastExceptions and force relinks
+ * for fast NativeArray specializations of builtin methods
+ */
+public interface NumericElements extends AnyElements {
+ //empty
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
index a9a1b5b2..ebaa3d6d 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -33,7 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* Implementation of {@link ArrayData} as soon as an Object has been
* written to the array
*/
-final class ObjectArrayData extends ArrayData {
+final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
/**
* The wrapped array
@@ -45,24 +48,52 @@ final class ObjectArrayData extends ArrayData {
* @param array an int array
* @param length a length, not necessarily array.length
*/
- ObjectArrayData(final Object array[], final int length) {
+ ObjectArrayData(final Object[] array, final int length) {
super(length);
assert array.length >= length;
this.array = array;
}
@Override
- public ArrayData copy() {
- return new ObjectArrayData(array.clone(), (int) length());
+ public final Class<?> getElementType() {
+ return Object.class;
+ }
+
+ @Override
+ public final Class<?> getBoxedElementType() {
+ return getElementType();
+ }
+
+ @Override
+ public final int getElementWeight() {
+ return 4;
+ }
+
+ @Override
+ public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
+ return otherData instanceof NumericElements ? this : otherData;
+ }
+
+ @Override
+ public ObjectArrayData copy() {
+ return new ObjectArrayData(array.clone(), (int)length());
}
@Override
public Object[] asObjectArray() {
- return Arrays.copyOf(array, (int) length());
+ return array.length == length() ? array.clone() : asObjectArrayCopy();
+ }
+
+ private Object[] asObjectArrayCopy() {
+ final long len = length();
+ assert len <= Integer.MAX_VALUE;
+ final Object[] copy = new Object[(int)len];
+ System.arraycopy(array, 0, copy, 0, (int)len);
+ return copy;
}
@Override
- public ArrayData convert(final Class<?> type) {
+ public ObjectArrayData convert(final Class<?> type) {
return this;
}
@@ -84,23 +115,15 @@ final class ObjectArrayData extends ArrayData {
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(this, safeIndex + 1);
}
-
- int newLength = array.length;
-
- while (newLength <= safeIndex) {
- newLength = ArrayData.nextSize(newLength);
- }
-
- if (array.length <= safeIndex) {
- array = Arrays.copyOf(array, newLength);
- Arrays.fill(array, (int) length(), newLength, ScriptRuntime.UNDEFINED);
+ final int alen = array.length;
+ if (safeIndex >= alen) {
+ final int newLength = ArrayData.nextSize((int)safeIndex);
+ array = Arrays.copyOf(array, newLength); //fill with undefined or OK? TODO
}
-
setLength(safeIndex + 1);
-
return this;
}
@@ -146,10 +169,45 @@ final class ObjectArrayData extends ArrayData {
@Override
public ArrayData setEmpty(final long lo, final long hi) {
- Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, Integer.MAX_VALUE), ScriptRuntime.EMPTY);
+ // hi parameter is inclusive, but Arrays.fill toIndex parameter is exclusive
+ Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi + 1, Integer.MAX_VALUE), ScriptRuntime.EMPTY);
return this;
}
+ private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "getElem", Object.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "setElem", void.class, int.class, Object.class).methodHandle();
+
+ @SuppressWarnings("unused")
+ private Object getElem(final int index) {
+ if (has(index)) {
+ return array[index];
+ }
+ throw new ClassCastException();
+ }
+
+ @SuppressWarnings("unused")
+ private void setElem(final int index, final Object elem) {
+ if (hasRoomFor(index)) {
+ array[index] = elem;
+ return;
+ }
+ throw new ClassCastException();
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType.isPrimitive()) {
+ return null;
+ }
+ return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return getContinuousElementSetter(SET_ELEM, Object.class);
+ }
+
+
@Override
public int getInt(final int index) {
return JSType.toInt32(array[index]);
@@ -188,12 +246,48 @@ final class ObjectArrayData extends ArrayData {
}
@Override
+ public long fastPush(final int arg) {
+ return fastPush((Object)arg);
+ }
+
+ @Override
+ public long fastPush(final long arg) {
+ return fastPush((Object)arg);
+ }
+
+ @Override
+ public long fastPush(final double arg) {
+ return fastPush((Object)arg);
+ }
+
+ @Override
+ public long fastPush(final Object arg) {
+ final int len = (int)length();
+ if (len == array.length) {
+ array = Arrays.copyOf(array, nextSize(len));
+ }
+ array[len] = arg;
+ return increaseLength();
+ }
+
+ @Override
+ public Object fastPopObject() {
+ if (length() == 0) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ final int newLength = (int)decreaseLength();
+ final Object elem = array[newLength];
+ array[newLength] = ScriptRuntime.EMPTY;
+ return elem;
+ }
+
+ @Override
public Object pop() {
if (length() == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int) (length() - 1);
+ final int newLength = (int)length() - 1;
final Object elem = array[newLength];
setEmpty(newLength);
setLength(newLength);
@@ -202,19 +296,30 @@ final class ObjectArrayData extends ArrayData {
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? (from + length()) : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
+ public ArrayData push(final boolean strict, final Object item) {
+ final long len = length();
+ final ArrayData newData = ensure(len);
+ if (newData == this) {
+ array[(int)len] = item;
+ return this;
+ }
+ return newData.set((int)len, item, strict);
+ }
+
+ @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
}
- final ArrayData returnValue = (removed == 0) ?
+ final ArrayData returnValue = removed == 0 ?
EMPTY_ARRAY : new ObjectArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
if (newLength != oldLength) {
@@ -234,4 +339,26 @@ final class ObjectArrayData extends ArrayData {
return returnValue;
}
+
+ @Override
+ public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
+ assert otherLength > 0 && thisLength > 0;
+
+ final Object[] otherArray = ((ObjectArrayData)otherData).array;
+ final int newLength = otherLength + thisLength;
+ final Object[] newArray = new Object[ArrayData.alignUp(newLength)];
+
+ System.arraycopy(array, 0, newArray, 0, thisLength);
+ System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
+
+ return new ObjectArrayData(newArray, newLength);
+ }
+
+ @Override
+ public String toString() {
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
index bc6de9f0..3e78f2df 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
-import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
/**
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
index ed99ce1c..ff569d44 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
@@ -28,6 +28,7 @@ package jdk.nashorn.internal.runtime.arrays;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -35,7 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* Handle arrays where the index is very large.
*/
class SparseArrayData extends ArrayData {
- static final long MAX_DENSE_LENGTH = 512 * 1024;
+ static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
/** Underlying array. */
private ArrayData underlying;
@@ -65,19 +66,19 @@ class SparseArrayData extends ArrayData {
@Override
public Object[] asObjectArray() {
- final int length = (int) Math.min(length(), Integer.MAX_VALUE);
- final int underlyingLength = (int) Math.min(length, underlying.length());
- final Object[] objArray = new Object[length];
+ final int len = (int)Math.min(length(), Integer.MAX_VALUE);
+ final int underlyingLength = (int)Math.min(len, underlying.length());
+ final Object[] objArray = new Object[len];
for (int i = 0; i < underlyingLength; i++) {
objArray[i] = underlying.getObject(i);
}
- Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED);
+ Arrays.fill(objArray, underlyingLength, len, ScriptRuntime.UNDEFINED);
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long key = entry.getKey();
- if (key <= Integer.MAX_VALUE) {
+ if (key < Integer.MAX_VALUE) {
objArray[(int)key] = entry.getValue();
} else {
break; // ascending key order
@@ -109,8 +110,9 @@ class SparseArrayData extends ArrayData {
@Override
public ArrayData shiftRight(final int by) {
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
- if (underlying.length() + by > maxDenseLength) {
- for (long i = maxDenseLength - by; i < underlying.length(); i++) {
+ final long len = underlying.length();
+ if (len + by > maxDenseLength) {
+ for (long i = maxDenseLength - by; i < len; i++) {
if (underlying.has((int) i)) {
newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
}
@@ -161,8 +163,9 @@ class SparseArrayData extends ArrayData {
underlying = underlying.set(index, value, strict);
setLength(Math.max(underlying.length(), length()));
} else {
- sparseMap.put(indexToKey(index), value);
- setLength(Math.max(index + 1, length()));
+ final Long longIndex = indexToKey(index);
+ sparseMap.put(longIndex, value);
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
@@ -175,8 +178,9 @@ class SparseArrayData extends ArrayData {
underlying = underlying.set(index, value, strict);
setLength(Math.max(underlying.length(), length()));
} else {
- sparseMap.put(indexToKey(index), value);
- setLength(Math.max(index + 1, length()));
+ final Long longIndex = indexToKey(index);
+ sparseMap.put(longIndex, value);
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -188,8 +192,9 @@ class SparseArrayData extends ArrayData {
underlying = underlying.set(index, value, strict);
setLength(Math.max(underlying.length(), length()));
} else {
- sparseMap.put(indexToKey(index), value);
- setLength(Math.max(index + 1, length()));
+ final Long longIndex = indexToKey(index);
+ sparseMap.put(longIndex, value);
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -201,8 +206,9 @@ class SparseArrayData extends ArrayData {
underlying = underlying.set(index, value, strict);
setLength(Math.max(underlying.length(), length()));
} else {
- sparseMap.put(indexToKey(index), value);
- setLength(Math.max(index + 1, length()));
+ final Long longIndex = indexToKey(index);
+ sparseMap.put(longIndex, value);
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -220,6 +226,11 @@ class SparseArrayData extends ArrayData {
}
@Override
+ public Type getOptimisticType() {
+ return underlying.getOptimisticType();
+ }
+
+ @Override
public int getInt(final int index) {
if (index >= 0 && index < maxDenseLength) {
return underlying.getInt(index);
@@ -228,6 +239,14 @@ class SparseArrayData extends ArrayData {
}
@Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ if (index >= 0 && index < maxDenseLength) {
+ return underlying.getIntOptimistic(index, programPoint);
+ }
+ return JSType.toInt32Optimistic(sparseMap.get(indexToKey(index)), programPoint);
+ }
+
+ @Override
public long getLong(final int index) {
if (index >= 0 && index < maxDenseLength) {
return underlying.getLong(index);
@@ -236,6 +255,14 @@ class SparseArrayData extends ArrayData {
}
@Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ if (index >= 0 && index < maxDenseLength) {
+ return underlying.getLongOptimistic(index, programPoint);
+ }
+ return JSType.toLongOptimistic(sparseMap.get(indexToKey(index)), programPoint);
+ }
+
+ @Override
public double getDouble(final int index) {
if (index >= 0 && index < maxDenseLength) {
return underlying.getDouble(index);
@@ -244,6 +271,14 @@ class SparseArrayData extends ArrayData {
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ if (index >= 0 && index < maxDenseLength) {
+ return underlying.getDouble(index);
+ }
+ return JSType.toNumberOptimistic(sparseMap.get(indexToKey(index)), programPoint);
+ }
+
+ @Override
public Object getObject(final int index) {
if (index >= 0 && index < maxDenseLength) {
return underlying.getObject(index);
@@ -291,27 +326,29 @@ class SparseArrayData extends ArrayData {
}
private static Long indexToKey(final int index) {
- return Long.valueOf(index & JSType.MAX_UINT);
+ return Long.valueOf(ArrayIndex.toLongIndex(index));
}
@Override
- protected ArrayData convert(final Class<?> type) {
+ public ArrayData convert(final Class<?> type) {
underlying = underlying.convert(type);
return this;
}
@Override
public Object pop() {
- if (length() == 0) {
+ final long len = length();
+ final long underlyingLen = underlying.length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- if (length() == underlying.length()) {
+ if (len == underlyingLen) {
final Object result = underlying.pop();
setLength(underlying.length());
return result;
}
- setLength(length() - 1);
- final Long key = Long.valueOf(length());
+ setLength(len - 1);
+ final Long key = Long.valueOf(len - 1);
return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
}
@@ -321,11 +358,13 @@ class SparseArrayData extends ArrayData {
final long start = from < 0 ? (from + length()) : from;
final long newLength = to - start;
+ final long underlyingLength = underlying.length();
+
if (start >= 0 && to <= maxDenseLength) {
- if (newLength <= underlying.length()) {
+ if (newLength <= underlyingLength) {
return underlying.slice(from, to);
}
- return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length(), newLength);
+ return underlying.slice(from, to).ensure(newLength - 1).delete(underlyingLength, newLength);
}
ArrayData sliced = EMPTY_ARRAY;
@@ -349,6 +388,7 @@ class SparseArrayData extends ArrayData {
if (nextKey != null) {
return nextKey;
}
+
return length();
}
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
new file mode 100644
index 00000000..40b3210b
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import java.lang.invoke.MethodHandle;
+import java.nio.Buffer;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
+
+/**
+ * The superclass of all ArrayData used by TypedArrays
+ *
+ * @param <T> buffer implementation
+ */
+public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayData {
+
+ /** wrapped native buffer */
+ protected final T nb;
+
+ /**
+ * Constructor
+ * @param nb wrapped native buffer
+ * @param elementLength length in elements
+ */
+ protected TypedArrayData(final T nb, final int elementLength) {
+ super(elementLength); //TODO is this right?
+ this.nb = nb;
+ }
+
+ /**
+ * Length in number of elements. Accessed from {@code ArrayBufferView}
+ * @return element length
+ */
+ public final int getElementLength() {
+ return (int)length();
+ }
+
+ /**
+ * Is this an unsigned array data?
+ * @return true if unsigned
+ */
+ public boolean isUnsigned() {
+ return false;
+ }
+
+ /**
+ * Is this a clamped array data?
+ * @return true if clamped
+ */
+ public boolean isClamped() {
+ return false;
+ }
+
+ @Override
+ public boolean canDelete(final int index, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public TypedArrayData<T> copy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object[] asObjectArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void shiftLeft(final int by) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ArrayData shiftRight(final int by) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ArrayData ensure(final long safeIndex) {
+ return this;
+ }
+
+ @Override
+ public ArrayData shrink(final long newLength) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public final boolean has(final int index) {
+ return 0 <= index && index < length();
+ }
+
+ @Override
+ public ArrayData delete(final int index) {
+ return this;
+ }
+
+ @Override
+ public ArrayData delete(final long fromIndex, final long toIndex) {
+ return this;
+ }
+
+ @Override
+ public TypedArrayData<T> convert(final Class<?> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object pop() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ArrayData slice(final long from, final long to) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Element getter method handle
+ * @return getter
+ */
+ protected abstract MethodHandle getGetElem();
+
+ /**
+ * Element setter method handle
+ * @return setter
+ */
+ protected abstract MethodHandle getSetElem();
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ final MethodHandle getter = getContinuousElementGetter(getClass(), getGetElem(), returnType, programPoint);
+ if (getter != null) {
+ return Lookup.filterReturnType(getter, returnType);
+ }
+ return getter;
+ }
+
+ @Override
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ return getContinuousElementSetter(getClass(), Lookup.filterArgumentType(getSetElem(), 2, elementType), elementType);
+ }
+
+ @Override
+ protected MethodHandle getContinuousElementSetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle setHas, final Class<?> elementType) {
+ final MethodHandle mh = Lookup.filterArgumentType(setHas, 2, elementType);
+ return MH.asType(mh, mh.type().changeParameterType(0, clazz));
+ }
+
+ @Override
+ public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = super.findFastGetIndexMethod(clazz, desc, request);
+
+ if (inv != null) {
+ return inv;
+ }
+
+ return null;
+ }
+
+ @Override
+ public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+ final GuardedInvocation inv = super.findFastSetIndexMethod(clazz, desc, request);
+
+ if (inv != null) {
+ return inv;
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
index 57046f8c..9865dcbb 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
@@ -26,9 +26,9 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
import java.lang.reflect.Array;
import jdk.nashorn.internal.runtime.BitVector;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* This filter handles the presence of undefined array elements.
@@ -39,13 +39,12 @@ final class UndefinedArrayFilter extends ArrayFilter {
UndefinedArrayFilter(final ArrayData underlying) {
super(underlying);
-
this.undefined = new BitVector(underlying.length());
}
@Override
public ArrayData copy() {
- UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
+ final UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
copy.getUndefined().copy(undefined);
return copy;
}
@@ -87,7 +86,6 @@ final class UndefinedArrayFilter extends ArrayFilter {
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
undefined.shiftRight(by, length());
-
return this;
}
@@ -107,7 +105,6 @@ final class UndefinedArrayFilter extends ArrayFilter {
public ArrayData shrink(final long newLength) {
super.shrink(newLength);
undefined.resize(length());
-
return this;
}
@@ -154,6 +151,15 @@ final class UndefinedArrayFilter extends ArrayFilter {
}
@Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ if (undefined.isSet(index)) {
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ return super.getIntOptimistic(index, programPoint);
+ }
+
+ @Override
public long getLong(final int index) {
if (undefined.isSet(index)) {
return 0L;
@@ -163,6 +169,15 @@ final class UndefinedArrayFilter extends ArrayFilter {
}
@Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ if (undefined.isSet(index)) {
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ return super.getLongOptimistic(index, programPoint);
+ }
+
+ @Override
public double getDouble(final int index) {
if (undefined.isSet(index)) {
return Double.NaN;
@@ -172,6 +187,15 @@ final class UndefinedArrayFilter extends ArrayFilter {
}
@Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ if (undefined.isSet(index)) {
+ throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+ }
+
+ return super.getDoubleOptimistic(index, programPoint);
+ }
+
+ @Override
public Object getObject(final int index) {
if (undefined.isSet(index)) {
return UNDEFINED;
diff --git a/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java b/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java
new file mode 100644
index 00000000..8b2ff471
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.events;
+
+import java.util.logging.Level;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.RewriteException;
+
+/**
+ * Subclass of runtime event for {@link RewriteException}. In order not
+ * to leak memory, RewriteExceptions get their return value destroyed
+ * and nulled out during recompilation. If we are running with event
+ * logging enabled, we need to retain the returnValue, hence the extra
+ * field
+ */
+public final class RecompilationEvent extends RuntimeEvent<RewriteException> {
+
+ private final Object returnValue;
+
+ /**
+ * Constructor
+ *
+ * @param level logging level
+ * @param rewriteException rewriteException wrapped by this RuntimEvent
+ * @param returnValue rewriteException return value - as we don't want to make
+ * {@code RewriteException.getReturnValueNonDestructive()} public, we pass it as
+ * an extra parameter, rather than querying the getter from another package.
+ */
+ public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
+ super(level, rewriteException);
+ assert Context.getContext().getLogger(RecompilableScriptFunctionData.class).isEnabled() :
+ "Unit test/instrumentation purpose only: RecompilationEvent instances should not be created without '--log=recompile', or we will leak memory in the general case";
+ this.returnValue = returnValue;
+ }
+
+ /**
+ * Get the preserved return value for the RewriteException
+ * @return return value
+ */
+ public Object getReturnValue() {
+ return returnValue;
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java b/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java
new file mode 100644
index 00000000..29a3714a
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.events;
+
+import java.util.logging.Level;
+import jdk.nashorn.internal.objects.NativeDebug;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * Class for representing a runtime event, giving less global dependencies than logger.
+ * Every {@link NativeDebug} object keeps a queue of RuntimeEvents that can be explored
+ * through the debug API.
+ *
+ * @param <T> class of the value this event wraps
+ */
+public class RuntimeEvent<T> {
+ /** Queue size for the runtime event buffer */
+ public static final int RUNTIME_EVENT_QUEUE_SIZE = Options.getIntProperty("nashorn.runtime.event.queue.size", 1024);
+
+ private final Level level;
+ private final T value;
+
+ /**
+ * Constructor
+ *
+ * @param level log level for runtime event to create
+ * @param object object to wrap
+ */
+ public RuntimeEvent(final Level level, final T object) {
+ this.level = level;
+ this.value = object;
+ }
+
+ /**
+ * Return the value wrapped in this runtime event
+ * @return value
+ */
+ public final T getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append('[').
+ append(level).
+ append("] ").
+ append(value == null ? "null" : getValueClass().getSimpleName()).
+ append(" value=").
+ append(value);
+
+ return sb.toString();
+ }
+
+ /**
+ * Descriptor for this runtime event, must be overridden and
+ * implemented, e.g. "RewriteException"
+ * @return event name
+ */
+ public final Class<?> getValueClass() {
+ return value.getClass();
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
index 48821036..749c4728 100644
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
@@ -26,8 +26,10 @@
package jdk.nashorn.internal.runtime.linker;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
@@ -35,14 +37,24 @@ import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.DynamicLinkerFactory;
+import jdk.internal.dynalink.GuardedInvocationFilter;
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
+import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.RuntimeCallSite;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.objects.ScriptFunctionImpl;
+import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.options.Options;
@@ -54,6 +66,25 @@ public final class Bootstrap {
/** Reference to the seed boostrap function */
public static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "bootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);
+ private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+
+ /**
+ * The default dynalink relink threshold for megamorphisism is 8. In the case
+ * of object fields only, it is fine. However, with dual fields, in order to get
+ * performance on benchmarks with a lot of object instantiation and then field
+ * reassignment, it can take slightly more relinks to become stable with type
+ * changes swapping out an entire proprety map and making a map guard fail.
+ * Therefore the relink threshold is set to 16 for dual fields (now the default).
+ * This doesn't seem to have any other negative performance implication.
+ *
+ * See for example octane.gbemu, run with --log=fields:warning to study
+ * megamorphic behavior
+ */
+ private static final int NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD =
+ ObjectClassGenerator.OBJECT_FIELDS_ONLY ?
+ 8 :
+ 16;
+
// do not create me!!
private Bootstrap() {
}
@@ -62,18 +93,31 @@ public final class Bootstrap {
static {
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker();
- final JSObjectLinker jsObjectLinker = new JSObjectLinker(nashornBeansLinker);
factory.setPrioritizedLinkers(
new NashornLinker(),
new NashornPrimitiveLinker(),
new NashornStaticClassLinker(),
- new BoundDynamicMethodLinker(),
+ new BoundCallableLinker(),
new JavaSuperAdapterLinker(),
- jsObjectLinker,
+ new JSObjectLinker(nashornBeansLinker),
+ new BrowserJSObjectLinker(nashornBeansLinker),
new ReflectionCheckLinker());
factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker());
factory.setSyncOnRelink(true);
- final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
+ factory.setPrelinkFilter(new GuardedInvocationFilter() {
+ @Override
+ public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
+ final CallSiteDescriptor desc = request.getCallSiteDescriptor();
+ return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType());
+ }
+ });
+ factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() {
+ @Override
+ public MethodHandle asType(final MethodHandle target, final MethodType newType) {
+ return unboxReturnType(target, newType);
+ }
+ });
+ final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
if (relinkThreshold > -1) {
factory.setUnstableRelinkThreshold(relinkThreshold);
}
@@ -95,19 +139,47 @@ public final class Bootstrap {
}
return obj instanceof ScriptFunction ||
- ((obj instanceof JSObject) && ((JSObject)obj).isFunction()) ||
- isDynamicMethod(obj) ||
+ isJSObjectFunction(obj) ||
+ BeansLinker.isDynamicMethod(obj) ||
+ obj instanceof BoundCallable ||
isFunctionalInterfaceObject(obj) ||
obj instanceof StaticClass;
}
/**
+ * Returns true if the given object is a strict callable
+ * @param callable the callable object to be checked for strictness
+ * @return true if the obj is a strict callable, false if it is a non-strict callable.
+ * @throws ECMAException with {@code TypeError} if the object is not a callable.
+ */
+ public static boolean isStrictCallable(final Object callable) {
+ if (callable instanceof ScriptFunction) {
+ return ((ScriptFunction)callable).isStrict();
+ } else if (isJSObjectFunction(callable)) {
+ return ((JSObject)callable).isStrictFunction();
+ } else if (callable instanceof BoundCallable) {
+ return isStrictCallable(((BoundCallable)callable).getCallable());
+ } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) {
+ return false;
+ }
+ throw notFunction(callable);
+ }
+
+ private static ECMAException notFunction(final Object obj) {
+ return typeError("not.a.function", ScriptRuntime.safeToString(obj));
+ }
+
+ private static boolean isJSObjectFunction(final Object obj) {
+ return obj instanceof JSObject && ((JSObject)obj).isFunction();
+ }
+
+ /**
* Returns if the given object is a dynalink Dynamic method
* @param obj object to be checked
* @return true if the obj is a dynamic method
*/
public static boolean isDynamicMethod(final Object obj) {
- return obj instanceof BoundDynamicMethod || BeansLinker.isDynamicMethod(obj);
+ return BeansLinker.isDynamicMethod(obj instanceof BoundCallable ? ((BoundCallable)obj).getCallable() : obj);
}
/**
@@ -148,6 +220,60 @@ public final class Bootstrap {
}
/**
+ * Boostrapper for math calls that may overflow
+ * @param lookup lookup
+ * @param name name of operation
+ * @param type method type
+ * @param programPoint program point to bind to callsite
+ *
+ * @return callsite for a math instrinic node
+ */
+ public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
+ final MethodHandle mh;
+ switch (name) {
+ case "iadd":
+ mh = JSType.ADD_EXACT.methodHandle();
+ break;
+ case "isub":
+ mh = JSType.SUB_EXACT.methodHandle();
+ break;
+ case "imul":
+ mh = JSType.MUL_EXACT.methodHandle();
+ break;
+ case "idiv":
+ mh = JSType.DIV_EXACT.methodHandle();
+ break;
+ case "irem":
+ mh = JSType.REM_EXACT.methodHandle();
+ break;
+ case "ineg":
+ mh = JSType.NEGATE_EXACT.methodHandle();
+ break;
+ case "ladd":
+ mh = JSType.ADD_EXACT_LONG.methodHandle();
+ break;
+ case "lsub":
+ mh = JSType.SUB_EXACT_LONG.methodHandle();
+ break;
+ case "lmul":
+ mh = JSType.MUL_EXACT_LONG.methodHandle();
+ break;
+ case "ldiv":
+ mh = JSType.DIV_EXACT_LONG.methodHandle();
+ break;
+ case "lrem":
+ mh = JSType.REM_EXACT_LONG.methodHandle();
+ break;
+ case "lneg":
+ mh = JSType.NEGATE_EXACT_LONG.methodHandle();
+ break;
+ default:
+ throw new AssertionError("unsupported math intrinsic");
+ }
+ return new ConstantCallSite(MH.insertArguments(mh, mh.type().parameterCount() - 1, programPoint));
+ }
+
+ /**
* Returns a dynamic invoker for a specified dynamic operation using the public lookup. You can use this method to
* create a method handle that when invoked acts completely as if it were a Nashorn-linked call site. An overview of
* available dynamic operations can be found in the
@@ -250,6 +376,20 @@ public final class Bootstrap {
/**
* Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
+ * {@link #createDynamicInvoker(String, Class, Class...)} but with an additional parameter to
+ * set the call site flags of the dynamic invoker.
+ * @param opDesc Dynalink dynamic operation descriptor.
+ * @param flags the call site flags for the operation
+ * @param rtype the return type for the operation
+ * @param ptypes the parameter types for the operation
+ * @return MethodHandle for invoking the operation.
+ */
+ public static MethodHandle createDynamicInvoker(final String opDesc, final int flags, final Class<?> rtype, final Class<?>... ptypes) {
+ return bootstrap(MethodHandles.publicLookup(), opDesc, MethodType.methodType(rtype, ptypes), flags).dynamicInvoker();
+ }
+
+ /**
+ * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
* {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a
* method type in the signature. See the discussion of that method for details.
* @param opDesc Dynalink dynamic operation descriptor.
@@ -261,14 +401,22 @@ public final class Bootstrap {
}
/**
- * Binds a bean dynamic method (returned by invoking {@code dyn:getMethod} on an object linked with
- * {@code BeansLinker} to a receiver.
- * @param dynamicMethod the dynamic method to bind
+ * Binds any object Nashorn can use as a [[Callable]] to a receiver and optionally arguments.
+ * @param callable the callable to bind
* @param boundThis the bound "this" value.
- * @return a bound dynamic method.
+ * @param boundArgs the bound arguments. Can be either null or empty array to signify no arguments are bound.
+ * @return a bound callable.
+ * @throws ECMAException with {@code TypeError} if the object is not a callable.
*/
- public static Object bindDynamicMethod(Object dynamicMethod, Object boundThis) {
- return new BoundDynamicMethod(dynamicMethod, boundThis);
+ public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
+ if (callable instanceof ScriptFunctionImpl) {
+ return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
+ } else if (callable instanceof BoundCallable) {
+ return ((BoundCallable)callable).bind(boundArgs);
+ } else if (isCallable(callable)) {
+ return new BoundCallable(callable, boundThis, boundArgs);
+ }
+ throw notFunction(callable);
}
/**
@@ -288,7 +436,7 @@ public final class Bootstrap {
* @param clazz the class being tested
* @param isStatic is access checked for static members (or instance members)
*/
- public static void checkReflectionAccess(Class<?> clazz, boolean isStatic) {
+ public static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
ReflectionCheckLinker.checkReflectionAccess(clazz, isStatic);
}
@@ -307,16 +455,41 @@ public final class Bootstrap {
/**
* Takes a guarded invocation, and ensures its method and guard conform to the type of the call descriptor, using
* all type conversions allowed by the linker's services. This method is used by Nashorn's linkers as a last step
- * before returning guarded invocations to the callers. Most of the code used to produce the guarded invocations
- * does not make an effort to coordinate types of the methods, and so a final type adjustment before a guarded
- * invocation is returned is the responsibility of the linkers themselves.
+ * before returning guarded invocations. Most of the code used to produce the guarded invocations does not make an
+ * effort to coordinate types of the methods, and so a final type adjustment before a guarded invocation is returned
+ * to the aggregating linker is the responsibility of the linkers themselves.
* @param inv the guarded invocation that needs to be type-converted. Can be null.
* @param linkerServices the linker services object providing the type conversions.
* @param desc the call site descriptor to whose method type the invocation needs to conform.
* @return the type-converted guarded invocation. If input is null, null is returned. If the input invocation
* already conforms to the requested type, it is returned unchanged.
*/
- static GuardedInvocation asType(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
- return inv == null ? null : inv.asType(linkerServices, desc.getMethodType());
+ static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
+ return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType());
+ }
+
+ /**
+ * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an unboxing
+ * conversion. This will ensure that nulls are unwrapped to false or 0.
+ * @param target the target method handle
+ * @param newType the desired new type. Note that this method does not adapt the method handle completely to the
+ * new type, it only adapts the return type; this is allowed as per
+ * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is what this method
+ * is used for.
+ * @return the method handle with adapted return type, if it required an unboxing conversion.
+ */
+ private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
+ final MethodType targetType = target.type();
+ final Class<?> oldReturnType = targetType.returnType();
+ if (TypeUtilities.isWrapperType(oldReturnType)) {
+ final Class<?> newReturnType = newType.returnType();
+ if (newReturnType.isPrimitive()) {
+ // The contract of setAutoConversionStrategy is such that the difference between newType and targetType
+ // can only be JLS method invocation conversions.
+ assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
+ return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType));
+ }
+ }
+ return target;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/BoundCallable.java b/src/jdk/nashorn/internal/runtime/linker/BoundCallable.java
new file mode 100644
index 00000000..a0eee0de
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/linker/BoundCallable.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import java.util.Arrays;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Represents a Nashorn callable bound to a receiver and optionally arguments. Note that objects of this class
+ * are just the tuples of a callable and a bound this and arguments, without any behavior. All the behavior is
+ * defined in the {@code BoundCallableLinker}.
+ */
+public final class BoundCallable {
+ private final Object callable;
+ private final Object boundThis;
+ private final Object[] boundArgs;
+
+ BoundCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
+ this.callable = callable;
+ this.boundThis = boundThis;
+ this.boundArgs = isEmptyArray(boundArgs) ? ScriptRuntime.EMPTY_ARRAY : boundArgs.clone();
+ }
+
+ private BoundCallable(final BoundCallable original, final Object[] extraBoundArgs) {
+ this.callable = original.callable;
+ this.boundThis = original.boundThis;
+ this.boundArgs = original.concatenateBoundArgs(extraBoundArgs);
+ }
+
+ Object getCallable() {
+ return callable;
+ }
+
+ Object getBoundThis() {
+ return boundThis;
+ }
+
+ Object[] getBoundArgs() {
+ return boundArgs;
+ }
+
+ BoundCallable bind(final Object[] extraBoundArgs) {
+ if (isEmptyArray(extraBoundArgs)) {
+ return this;
+ }
+ return new BoundCallable(this, extraBoundArgs);
+ }
+
+ private Object[] concatenateBoundArgs(final Object[] extraBoundArgs) {
+ if (boundArgs.length == 0) {
+ return extraBoundArgs.clone();
+ }
+ final int origBoundArgsLen = boundArgs.length;
+ final int extraBoundArgsLen = extraBoundArgs.length;
+ final Object[] newBoundArgs = new Object[origBoundArgsLen + extraBoundArgsLen];
+ System.arraycopy(boundArgs, 0, newBoundArgs, 0, origBoundArgsLen);
+ System.arraycopy(extraBoundArgs, 0, newBoundArgs, origBoundArgsLen, extraBoundArgsLen);
+ return newBoundArgs;
+ }
+
+ private static boolean isEmptyArray(final Object[] a) {
+ return a == null || a.length == 0;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder b = new StringBuilder(callable.toString()).append(" on ").append(boundThis);
+ if (boundArgs.length != 0) {
+ b.append(" with ").append(Arrays.toString(boundArgs));
+ }
+ return b.toString();
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java b/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
new file mode 100644
index 00000000..d52063bf
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.Guards;
+
+/**
+ * Links {@link BoundCallable} objects. Passes through to linker services for linking a callable (for either
+ * "dyn:call" or "dyn:new"), and modifies the returned invocation to deal with the receiver and argument binding.
+ */
+final class BoundCallableLinker implements TypeBasedGuardingDynamicLinker {
+ @Override
+ public boolean canLinkType(final Class<?> type) {
+ return type == BoundCallable.class;
+ }
+
+ @Override
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
+ final Object objBoundCallable = linkRequest.getReceiver();
+ if(!(objBoundCallable instanceof BoundCallable)) {
+ return null;
+ }
+
+ final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
+ if (descriptor.getNameTokenCount() < 2 || !"dyn".equals(descriptor.getNameToken(CallSiteDescriptor.SCHEME))) {
+ return null;
+ }
+ final String operation = descriptor.getNameToken(CallSiteDescriptor.OPERATOR);
+ // We need to distinguish "dyn:new" from "dyn:call" because "dyn:call" sites have parameter list of the form
+ // "callee, this, args", while "dyn:call" sites have "callee, args" -- they lack the "this" parameter.
+ final boolean isCall;
+ if ("new".equals(operation)) {
+ isCall = false;
+ } else if ("call".equals(operation)) {
+ isCall = true;
+ } else {
+ // Only dyn:call and dyn:new are supported.
+ return null;
+ }
+ final BoundCallable boundCallable = (BoundCallable)objBoundCallable;
+ final Object callable = boundCallable.getCallable();
+ final Object boundThis = boundCallable.getBoundThis();
+
+ // We need to ask the linker services for a delegate invocation on the target callable.
+
+ // Replace arguments (boundCallable[, this], args) => (callable[, boundThis], boundArgs, args) when delegating
+ final Object[] args = linkRequest.getArguments();
+ final Object[] boundArgs = boundCallable.getBoundArgs();
+ final int argsLen = args.length;
+ final int boundArgsLen = boundArgs.length;
+ final Object[] newArgs = new Object[argsLen + boundArgsLen];
+ newArgs[0] = callable;
+ final int firstArgIndex;
+ if (isCall) {
+ newArgs[1] = boundThis;
+ firstArgIndex = 2;
+ } else {
+ firstArgIndex = 1;
+ }
+ System.arraycopy(boundArgs, 0, newArgs, firstArgIndex, boundArgsLen);
+ System.arraycopy(args, firstArgIndex, newArgs, firstArgIndex + boundArgsLen, argsLen - firstArgIndex);
+
+ // Use R(T0, T1, T2, ...) => R(callable.class, boundThis.class, boundArg0.class, ..., boundArgn.class, T2, ...)
+ // call site type when delegating to underlying linker (for dyn:new, there's no this).
+ final MethodType type = descriptor.getMethodType();
+ // Use R(T0, ...) => R(callable.class, ...)
+ MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass());
+ if (isCall) {
+ // R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...)
+ newMethodType = newMethodType.changeParameterType(1, boundThis.getClass());
+ }
+ // R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...)
+ for(int i = boundArgs.length; i-- > 0;) {
+ newMethodType = newMethodType.insertParameterTypes(firstArgIndex, boundArgs[i] == null ? Object.class : boundArgs[i].getClass());
+ }
+ final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(newMethodType);
+
+ // Delegate to target's linker
+ final GuardedInvocation inv = linkerServices.getGuardedInvocation(linkRequest.replaceArguments(newDescriptor, newArgs));
+ if(inv == null) {
+ return null;
+ }
+
+ // Bind (callable[, boundThis], boundArgs) to the delegate handle
+ final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0,
+ Arrays.copyOf(newArgs, firstArgIndex + boundArgs.length));
+ final Class<?> p0Type = type.parameterType(0);
+ final MethodHandle droppingHandle;
+ if (isCall) {
+ // Ignore incoming boundCallable and this
+ droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
+ } else {
+ // Ignore incoming boundCallable
+ droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type);
+ }
+ // Identity guard on boundCallable object
+ final MethodHandle newGuard = Guards.getIdentityGuard(boundCallable);
+ return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java b/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
deleted file mode 100644
index 77c1618b..00000000
--- a/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.linker;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import jdk.internal.dynalink.CallSiteDescriptor;
-import jdk.internal.dynalink.beans.BeansLinker;
-import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.internal.dynalink.linker.LinkerServices;
-import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
-import jdk.internal.dynalink.support.Guards;
-
-/**
- * Links {@code BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method
- * (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding.
- */
-final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
- @Override
- public boolean canLinkType(Class<?> type) {
- return type == BoundDynamicMethod.class;
- }
-
- @Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception {
- final Object objBoundDynamicMethod = linkRequest.getReceiver();
- if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) {
- return null;
- }
-
- final BoundDynamicMethod boundDynamicMethod = (BoundDynamicMethod)objBoundDynamicMethod;
- final Object dynamicMethod = boundDynamicMethod.getDynamicMethod();
- final Object boundThis = boundDynamicMethod.getBoundThis();
-
- // Replace arguments (boundDynamicMethod, this, ...) => (dynamicMethod, boundThis, ...) when delegating to
- // BeansLinker
- final Object[] args = linkRequest.getArguments();
- args[0] = dynamicMethod;
- args[1] = boundThis;
-
- // Use R(T0, T1, ...) => R(dynamicMethod.class, boundThis.class, ...) call site type when delegating to
- // BeansLinker.
- final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
- final MethodType type = descriptor.getMethodType();
- final Class<?> dynamicMethodClass = dynamicMethod.getClass();
- final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(
- type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
-
- // Delegate to BeansLinker
- final GuardedInvocation inv = NashornBeansLinker.getGuardedInvocation(BeansLinker.getLinkerForClass(dynamicMethodClass),
- linkRequest.replaceArguments(newDescriptor, args), linkerServices);
- if(inv == null) {
- return null;
- }
-
- // Bind (dynamicMethod, boundThis) to the handle
- final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0, dynamicMethod, boundThis);
- final Class<?> p0Type = type.parameterType(0);
- // Ignore incoming (boundDynamicMethod, this)
- final MethodHandle droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
- // Identity guard on boundDynamicMethod object
- final MethodHandle newGuard = Guards.getIdentityGuard(boundDynamicMethod);
-
- return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
- }
-}
diff --git a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
new file mode 100644
index 00000000..d2f23e82
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects.
+ */
+final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
+ private static final ClassLoader myLoader = BrowserJSObjectLinker.class.getClassLoader();
+ private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject";
+ // not final because this is lazily initialized
+ // when we hit a subclass for the first time.
+ private static volatile Class<?> jsObjectClass;
+ private final NashornBeansLinker nashornBeansLinker;
+
+ BrowserJSObjectLinker(final NashornBeansLinker nashornBeansLinker) {
+ this.nashornBeansLinker = nashornBeansLinker;
+ }
+
+ @Override
+ public boolean canLinkType(final Class<?> type) {
+ return canLinkTypeStatic(type);
+ }
+
+ static boolean canLinkTypeStatic(final Class<?> type) {
+ if (jsObjectClass != null && jsObjectClass.isAssignableFrom(type)) {
+ return true;
+ }
+
+ // check if this class is a subclass of JSObject
+ Class<?> clazz = type;
+ while (clazz != null) {
+ if (clazz.getClassLoader() == myLoader &&
+ clazz.getName().equals(JSOBJECT_CLASS)) {
+ jsObjectClass = clazz;
+ return true;
+ }
+ clazz = clazz.getSuperclass();
+ }
+
+ return false;
+ }
+
+ private static void checkJSObjectClass() {
+ assert jsObjectClass != null : JSOBJECT_CLASS + " not found!";
+ }
+
+ @Override
+ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
+ final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
+ final Object self = requestWithoutContext.getReceiver();
+ final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
+ checkJSObjectClass();
+
+ if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
+ // We only support standard "dyn:*[:*]" operations
+ return null;
+ }
+
+ final GuardedInvocation inv;
+ if (jsObjectClass.isInstance(self)) {
+ inv = lookup(desc, request, linkerServices);
+ } else {
+ throw new AssertionError(); // Should never reach here.
+ }
+
+ return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
+ }
+
+ private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception {
+ final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
+ final int c = desc.getNameTokenCount();
+
+ switch (operator) {
+ case "getProp":
+ case "getElem":
+ case "getMethod":
+ if (c > 2) {
+ return findGetMethod(desc);
+ }
+ // For indexed get, we want GuardedInvocation from beans linker and pass it.
+ // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access.
+ return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
+ case "setProp":
+ case "setElem":
+ return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
+ case "call":
+ return findCallMethod(desc);
+ default:
+ return null;
+ }
+ }
+
+ private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name);
+ return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
+ }
+
+ private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) {
+ final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation());
+ return inv.replaceMethods(getter, inv.getGuard());
+ }
+
+ private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
+ final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2));
+ return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
+ }
+
+ private static GuardedInvocation findSetIndexMethod() {
+ return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
+ }
+
+ private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
+ final MethodHandle call = MH.insertArguments(JSOBJECT_CALL, 1, "call");
+ return new GuardedInvocation(MH.asCollector(call, Object[].class, desc.getMethodType().parameterCount() - 1), IS_JSOBJECT_GUARD);
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean isJSObject(final Object self) {
+ return jsObjectClass.isInstance(self);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object get(final MethodHandle fallback, final Object jsobj, final Object key) throws Throwable {
+ if (key instanceof Integer) {
+ return JSOBJECT_GETSLOT.invokeExact(jsobj, (int)key);
+ } else if (key instanceof Number) {
+ final int index = getIndex((Number)key);
+ if (index > -1) {
+ return JSOBJECT_GETSLOT.invokeExact(jsobj, index);
+ }
+ } else if (key instanceof String) {
+ final String name = (String)key;
+ if (name.indexOf('(') != -1) {
+ return fallback.invokeExact(jsobj, key);
+ }
+ return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ private static void put(final Object jsobj, final Object key, final Object value) throws Throwable {
+ if (key instanceof Integer) {
+ JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value);
+ } else if (key instanceof Number) {
+ JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value);
+ } else if (key instanceof String) {
+ JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value);
+ }
+ }
+
+ private static int getIndex(final Number n) {
+ final double value = n.doubleValue();
+ return JSType.isRepresentableAsInt(value) ? (int)value : -1;
+ }
+
+ private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+ // method handles of the current class
+ private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH_S("isJSObject", boolean.class, Object.class);
+ private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class);
+ private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class);
+
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), BrowserJSObjectLinker.class, name, MH.type(rtype, types));
+ }
+
+ // method handles of netscape.javascript.JSObject class
+ // These are in separate class as we lazily initialize these
+ // method handles when we hit a subclass of JSObject first time.
+ static class JSObjectHandles {
+ // method handles of JSObject class
+ static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class).asType(MH.type(Object.class, Object.class, String.class));
+ static final MethodHandle JSOBJECT_GETSLOT = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class));
+ static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class).asType(MH.type(Void.TYPE, Object.class, String.class, Object.class));
+ static final MethodHandle JSOBJECT_SETSLOT = findJSObjectMH_V("setSlot", Void.TYPE, int.class, Object.class).asType(MH.type(Void.TYPE, Object.class, int.class, Object.class));
+ static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, String.class, Object[].class).asType(MH.type(Object.class, Object.class, String.class, Object[].class));
+
+ private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ checkJSObjectClass();
+ return MH.findVirtual(MethodHandles.publicLookup(), jsObjectClass, name, MH.type(rtype, types));
+ }
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java b/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
index b139da1c..6a3d933f 100644
--- a/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
+++ b/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
@@ -75,7 +75,7 @@ final class ClassAndLoader {
return representativeClass;
}
- boolean canSee(ClassAndLoader other) {
+ boolean canSee(final ClassAndLoader other) {
try {
final Class<?> otherClass = other.getRepresentativeClass();
return Class.forName(otherClass.getName(), false, getLoader()) == otherClass;
diff --git a/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java b/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
index e6d13c20..19fe6bd7 100644
--- a/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
+++ b/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
@@ -90,7 +90,7 @@ public final class InvokeByName {
if(plength == 0) {
finalPtypes = new Class<?>[] { Object.class, targetClass };
} else {
- finalPtypes = new Class[plength + 2];
+ finalPtypes = new Class<?>[plength + 2];
finalPtypes[0] = Object.class;
finalPtypes[1] = targetClass;
System.arraycopy(ptypes, 0, finalPtypes, 2, plength);
diff --git a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
index 52fb46bc..aaf5a2c3 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
@@ -81,7 +81,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
final GuardedInvocation inv;
if (self instanceof JSObject) {
- inv = lookup(desc);
+ inv = lookup(desc, request, linkerServices);
} else if (self instanceof Map || self instanceof Bindings) {
// guard to make sure the Map or Bindings does not turn into JSObject later!
final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
@@ -91,7 +91,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
throw new AssertionError(); // Should never reach here.
}
- return Bootstrap.asType(inv, linkerServices, desc);
+ return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
}
@Override
@@ -110,14 +110,20 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
}
- private static GuardedInvocation lookup(final CallSiteDescriptor desc) {
+ private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception {
final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
final int c = desc.getNameTokenCount();
+
switch (operator) {
case "getProp":
case "getElem":
case "getMethod":
- return c > 2 ? findGetMethod(desc) : findGetIndexMethod();
+ if (c > 2) {
+ return findGetMethod(desc);
+ }
+ // For indexed get, we want get GuardedInvocation beans linker and pass it.
+ // JSObjectLinker.get uses this fallback getter for explicit signature method access.
+ return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
case "setProp":
case "setElem":
return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
@@ -131,31 +137,37 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
}
private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
- final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, desc.getNameToken(2));
- return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD);
+ final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+ final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name);
+ return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
}
- private static GuardedInvocation findGetIndexMethod() {
- return new GuardedInvocation(JSOBJECTLINKER_GET, null, IS_JSOBJECT_GUARD);
+ private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) {
+ final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation());
+ return inv.replaceMethods(getter, inv.getGuard());
}
private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2));
- return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD);
+ return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
}
private static GuardedInvocation findSetIndexMethod() {
- return new GuardedInvocation(JSOBJECTLINKER_PUT, null, IS_JSOBJECT_GUARD);
+ return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
}
private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
- final MethodHandle func = MH.asCollector(JSOBJECT_CALL, Object[].class, desc.getMethodType().parameterCount() - 2);
- return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD);
+ // TODO: if call site is already a vararg, don't do asCollector
+ MethodHandle mh = JSOBJECT_CALL;
+ if (NashornCallSiteDescriptor.isApplyToCall(desc)) {
+ mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL);
+ }
+ return new GuardedInvocation(MH.asCollector(mh, Object[].class, desc.getMethodType().parameterCount() - 2), IS_JSOBJECT_GUARD);
}
private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
final MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1);
- return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD);
+ return new GuardedInvocation(func, IS_JSOBJECT_GUARD);
}
@SuppressWarnings("unused")
@@ -164,7 +176,8 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
}
@SuppressWarnings("unused")
- private static Object get(final Object jsobj, final Object key) {
+ private static Object get(final MethodHandle fallback, final Object jsobj, final Object key)
+ throws Throwable {
if (key instanceof Integer) {
return ((JSObject)jsobj).getSlot((Integer)key);
} else if (key instanceof Number) {
@@ -173,7 +186,12 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
return ((JSObject)jsobj).getSlot(index);
}
} else if (key instanceof String) {
- return ((JSObject)jsobj).getMember((String)key);
+ final String name = (String)key;
+ // get with method name and signature. delegate it to beans linker!
+ if (name.indexOf('(') != -1) {
+ return fallback.invokeExact(jsobj, key);
+ }
+ return ((JSObject)jsobj).getMember(name);
}
return null;
}
@@ -195,8 +213,8 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
}
@SuppressWarnings("unused")
- private static long toInt64(final JSObject obj) {
- return JSType.toInt64(toNumber(obj));
+ private static long toLong(final JSObject obj) {
+ return JSType.toLong(toNumber(obj));
}
private static double toNumber(final JSObject obj) {
@@ -213,41 +231,48 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
return JSType.isRepresentableAsInt(value) ? (int)value : -1;
}
+ @SuppressWarnings("unused")
+ private static Object callToApply(final MethodHandle mh, final JSObject obj, final Object thiz, final Object... args) {
+ assert args.length >= 2;
+ final Object receiver = args[0];
+ final Object[] arguments = new Object[args.length - 1];
+ System.arraycopy(args, 1, arguments, 0, arguments.length);
+ try {
+ return mh.invokeExact(obj, thiz, new Object[] { receiver, arguments });
+ } catch (final RuntimeException | Error e) {
+ throw e;
+ } catch (final Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
// method handles of the current class
- private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH("isJSObject", boolean.class, Object.class);
- private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH("get", Object.class, Object.class, Object.class);
- private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class);
+ private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH_S("isJSObject", boolean.class, Object.class);
+ private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class);
+ private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class);
// method handles of JSObject class
- private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH("getMember", Object.class, String.class);
- private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH("setMember", Void.TYPE, String.class, Object.class);
- private static final MethodHandle JSOBJECT_CALL = findJSObjectMH("call", Object.class, Object.class, Object[].class);
- private static final MethodHandle JSOBJECT_NEW = findJSObjectMH("newObject", Object.class, Object[].class);
+ private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class);
+ private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class);
+ private static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, Object.class, Object[].class);
+ private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class);
+ private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class);
private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>();
static {
- CONVERTERS.put(boolean.class, findOwnMH("toBoolean", boolean.class, JSObject.class));
- CONVERTERS.put(int.class, findOwnMH("toInt32", int.class, JSObject.class));
- CONVERTERS.put(long.class, findOwnMH("toInt64", long.class, JSObject.class));
- CONVERTERS.put(double.class, findOwnMH("toNumber", double.class, JSObject.class));
- }
-
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return findMH(name, JSObjectLinker.class, rtype, types);
+ CONVERTERS.put(boolean.class, findOwnMH_S("toBoolean", boolean.class, JSObject.class));
+ CONVERTERS.put(int.class, findOwnMH_S("toInt32", int.class, JSObject.class));
+ CONVERTERS.put(long.class, findOwnMH_S("toLong", long.class, JSObject.class));
+ CONVERTERS.put(double.class, findOwnMH_S("toNumber", double.class, JSObject.class));
}
- private static MethodHandle findJSObjectMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return findMH(name, JSObject.class, rtype, types);
+ private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types));
}
- private static MethodHandle findMH(final String name, final Class<?> target, final Class<?> rtype, final Class<?>... types) {
- final MethodType mt = MH.type(rtype, types);
- try {
- return MH.findStatic(MethodHandles.lookup(), target, name, mt);
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), target, name, mt);
- }
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), JSObjectLinker.class, name, MH.type(rtype, types));
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 6b3acf63..7986b8b4 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -56,7 +56,9 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Handle;
@@ -64,7 +66,9 @@ import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
+import jdk.nashorn.api.scripting.ScriptUtils;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
@@ -131,9 +135,12 @@ import sun.reflect.CallerSensitive;
* implemented securely.
*/
final class JavaAdapterBytecodeGenerator {
- static final Type OBJECT_TYPE = Type.getType(Object.class);
+ private static final Type SCRIPTUTILS_TYPE = Type.getType(ScriptUtils.class);
+ private static final Type OBJECT_TYPE = Type.getType(Object.class);
+ private static final Type CLASS_TYPE = Type.getType(Class.class);
static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName();
+ static final String SCRIPTUTILS_TYPE_NAME = SCRIPTUTILS_TYPE.getInternalName();
static final String INIT = "<init>";
@@ -145,6 +152,7 @@ final class JavaAdapterBytecodeGenerator {
static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
+ private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
private static final Type STRING_TYPE = Type.getType(String.class);
private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class);
@@ -166,7 +174,12 @@ final class JavaAdapterBytecodeGenerator {
private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor();
private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE);
- private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class));
+ private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(CLASS_TYPE);
+ private static final String EXPORT_RETURN_VALUE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE);
+ private static final String UNWRAP_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE);
+ private static final String GET_CONVERTER_METHOD_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, CLASS_TYPE);
+ private static final String TO_CHAR_PRIMITIVE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.CHAR_TYPE, OBJECT_TYPE);
+ private static final String TO_STRING_METHOD_DESCRIPTOR = Type.getMethodDescriptor(STRING_TYPE, OBJECT_TYPE);
// Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
// it's a java.* package.
@@ -177,6 +190,7 @@ final class JavaAdapterBytecodeGenerator {
private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
private static final String CLASS_INIT = "<clinit>";
+ static final String CONVERTER_INIT = "<converter-init>";
// Method name prefix for invoking super-methods
static final String SUPER_PREFIX = "super$";
@@ -206,6 +220,22 @@ final class JavaAdapterBytecodeGenerator {
private boolean autoConvertibleFromFunction = false;
private boolean hasExplicitFinalizer = false;
+ /**
+ * Names of static fields holding type converter method handles for return value conversion. We are emitting code
+ * for invoking these explicitly after the delegate handle is invoked, instead of doing an asType or
+ * filterReturnValue on the delegate handle, as that would create a new converter handle wrapping the function's
+ * handle for every instance of the adapter, causing the handle.invokeExact() call sites to become megamorphic.
+ */
+ private final Map<Class<?>, String> converterFields = new LinkedHashMap<>();
+
+ /**
+ * Subset of possible return types for all methods; namely, all possible return types of the SAM methods (we
+ * identify SAM types by having all of their abstract methods share a single name, so there can be multiple
+ * overloads with multiple return types. We use this set when emitting the constructor taking a ScriptFunction (the
+ * SAM initializer) to avoid populating converter fields that will never be used by SAM methods.
+ */
+ private final Set<Class<?>> samReturnTypes = new HashSet<>();
+
private final ClassWriter cw;
/**
@@ -243,6 +273,7 @@ final class JavaAdapterBytecodeGenerator {
gatherMethods(interfaces);
samName = abstractMethodNames.size() == 1 ? abstractMethodNames.iterator().next() : null;
generateHandleFields();
+ generateConverterFields();
if(classOverride) {
generateClassInit();
}
@@ -315,6 +346,24 @@ final class JavaAdapterBytecodeGenerator {
}
}
+ private void generateConverterFields() {
+ final int flags = ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0);
+ for (final MethodInfo mi: methodInfos) {
+ final Class<?> returnType = mi.type.returnType();
+ // Handle primitive types, Object, and String specially
+ if(!returnType.isPrimitive() && returnType != Object.class && returnType != String.class) {
+ if(!converterFields.containsKey(returnType)) {
+ final String name = nextName("convert");
+ converterFields.put(returnType, name);
+ if(mi.getName().equals(samName)) {
+ samReturnTypes.add(returnType);
+ }
+ cw.visitField(flags, name, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
+ }
+ }
+ }
+ }
+
private void generateClassInit() {
final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
@@ -334,8 +383,7 @@ final class JavaAdapterBytecodeGenerator {
for (final MethodInfo mi : methodInfos) {
if(mi.getName().equals(samName)) {
mv.dup();
- mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR, false);
+ loadMethodTypeAndGetHandle(mv, mi, GET_HANDLE_FUNCTION_DESCRIPTOR);
} else {
mv.visitInsn(ACONST_NULL);
}
@@ -351,8 +399,7 @@ final class JavaAdapterBytecodeGenerator {
for (final MethodInfo mi : methodInfos) {
mv.dup();
mv.aconst(mi.getName());
- mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
+ loadMethodTypeAndGetHandle(mv, mi, GET_HANDLE_OBJECT_DESCRIPTOR);
mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -363,9 +410,41 @@ final class JavaAdapterBytecodeGenerator {
invokeGetGlobalWithNullCheck(mv);
mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
+ generateConverterInit(mv, false);
endInitMethod(mv);
}
+ private void generateConverterInit(final InstructionAdapter mv, final boolean samOnly) {
+ assert !samOnly || !classOverride;
+ for(final Map.Entry<Class<?>, String> converterField: converterFields.entrySet()) {
+ final Class<?> returnType = converterField.getKey();
+ if(!classOverride) {
+ mv.visitVarInsn(ALOAD, 0);
+ }
+
+ if(samOnly && !samReturnTypes.contains(returnType)) {
+ mv.visitInsn(ACONST_NULL);
+ } else {
+ mv.aconst(Type.getType(converterField.getKey()));
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getObjectConverter", GET_CONVERTER_METHOD_DESCRIPTOR, false);
+ }
+
+ if(classOverride) {
+ mv.putstatic(generatedClassName, converterField.getValue(), METHOD_HANDLE_TYPE_DESCRIPTOR);
+ } else {
+ mv.putfield(generatedClassName, converterField.getValue(), METHOD_HANDLE_TYPE_DESCRIPTOR);
+ }
+ }
+ }
+
+ private static void loadMethodTypeAndGetHandle(final InstructionAdapter mv, final MethodInfo mi, final String getHandleDescriptor) {
+ // NOTE: we're using generic() here because we'll be linking to the "generic" invoker version of
+ // the functions anyway, so we cut down on megamorphism in the invokeExact() calls in adapter
+ // bodies. Once we start linking to type-specializing invokers, this should be changed.
+ mv.aconst(Type.getMethodType(mi.type.generic().toMethodDescriptorString()));
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
+ }
+
private static void invokeGetGlobalWithNullCheck(final InstructionAdapter mv) {
invokeGetGlobal(mv);
mv.dup();
@@ -422,7 +501,7 @@ final class JavaAdapterBytecodeGenerator {
// Invoke super constructor with the same arguments.
mv.visitVarInsn(ALOAD, 0);
int offset = 1; // First arg is at position 1, after this.
- for (Type argType: argTypes) {
+ for (final Type argType: argTypes) {
mv.load(offset, argType);
offset += argType.getSize();
}
@@ -458,8 +537,8 @@ final class JavaAdapterBytecodeGenerator {
final int argLen = originalArgTypes.length;
final Type[] newArgTypes = new Type[argLen + 1];
- // Insert ScriptFunction|Object as the last argument to the constructor
- final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : OBJECT_TYPE;
+ // Insert ScriptFunction|ScriptObject as the last argument to the constructor
+ final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : SCRIPT_OBJECT_TYPE;
newArgTypes[argLen] = extraArgumentType;
System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
@@ -497,8 +576,7 @@ final class JavaAdapterBytecodeGenerator {
if(!fromFunction) {
mv.aconst(mi.getName());
}
- mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
+ loadMethodTypeAndGetHandle(mv, mi, getHandleDescriptor);
}
mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -508,6 +586,36 @@ final class JavaAdapterBytecodeGenerator {
invokeGetGlobalWithNullCheck(mv);
mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
+ // Initialize converters
+ generateConverterInit(mv, fromFunction);
+ endInitMethod(mv);
+
+ if (! fromFunction) {
+ newArgTypes[argLen] = OBJECT_TYPE;
+ final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
+ Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
+ generateOverridingConstructorWithObjectParam(mv2, ctor, originalCtorType.getDescriptor());
+ }
+ }
+
+ // Object additional param accepting constructor - generated to handle null and undefined value
+ // for script adapters. This is effectively to throw TypeError on such script adapters. See
+ // JavaAdapterServices.getHandle as well.
+ private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final Constructor<?> ctor, final String ctorDescriptor) {
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ final Class<?>[] argTypes = ctor.getParameterTypes();
+ int offset = 1; // First arg is at position 1, after this.
+ for (int i = 0; i < argTypes.length; ++i) {
+ final Type argType = Type.getType(argTypes[i]);
+ mv.load(offset, argType);
+ offset += argType.getSize();
+ }
+ mv.invokespecial(superClassName, INIT, ctorDescriptor, false);
+ mv.visitVarInsn(ALOAD, offset);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ACONST_NULL);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
endInitMethod(mv);
}
@@ -622,7 +730,8 @@ final class JavaAdapterBytecodeGenerator {
final Label handleDefined = new Label();
- final Type asmReturnType = Type.getType(type.returnType());
+ final Class<?> returnType = type.returnType();
+ final Type asmReturnType = Type.getType(returnType);
// See if we have overriding method handle defined
if(classOverride) {
@@ -632,7 +741,8 @@ final class JavaAdapterBytecodeGenerator {
mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
// stack: [handle]
- jumpIfNonNullKeepOperand(mv, handleDefined);
+ mv.visitInsn(DUP);
+ mv.visitJumpInsn(IFNONNULL, handleDefined);
// No handle is available, fall back to default behavior
if(Modifier.isAbstract(method.getModifiers())) {
@@ -642,6 +752,7 @@ final class JavaAdapterBytecodeGenerator {
mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
mv.athrow();
} else {
+ mv.visitInsn(POP);
// If the super method is not abstract, delegate to it.
emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
}
@@ -703,17 +814,20 @@ final class JavaAdapterBytecodeGenerator {
mv.visitVarInsn(ISTORE, globalsDifferVar);
// stack: [handle]
- // Load all parameters back on stack for dynamic invocation.
+ // Load all parameters back on stack for dynamic invocation. NOTE: since we're using a generic
+ // Object(Object, Object, ...) type signature for the method, we must box all arguments here.
int varOffset = 1;
for (final Type t : asmArgTypes) {
mv.load(varOffset, t);
+ boxStackTop(mv, t);
varOffset += t.getSize();
}
// Invoke the target method handle
final Label tryBlockStart = new Label();
mv.visitLabel(tryBlockStart);
- mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
+ emitInvokeExact(mv, type.generic());
+ convertReturnValue(mv, returnType, asmReturnType);
final Label tryBlockEnd = new Label();
mv.visitLabel(tryBlockEnd);
emitFinally(mv, currentGlobalVar, globalsDifferVar);
@@ -743,7 +857,7 @@ final class JavaAdapterBytecodeGenerator {
mv.visitLabel(methodEnd);
mv.visitLocalVariable("currentGlobal", GLOBAL_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd, currentGlobalVar);
- mv.visitLocalVariable("globalsDiffer", Type.INT_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
+ mv.visitLocalVariable("globalsDiffer", Type.BOOLEAN_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
if(throwableDeclared) {
mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, THROWABLE_TYPE_NAME);
@@ -759,16 +873,110 @@ final class JavaAdapterBytecodeGenerator {
endMethod(mv);
}
- /**
- * Emits code for jumping to a label if the top stack operand is not null. The operand is kept on the stack if it
- * is not null (so is available to code at the jump address) and is popped if it is null.
- * @param mv the instruction adapter being used to emit code
- * @param label the label to jump to
- */
- private static void jumpIfNonNullKeepOperand(final InstructionAdapter mv, final Label label) {
- mv.visitInsn(DUP);
- mv.visitJumpInsn(IFNONNULL, label);
- mv.visitInsn(POP);
+ private void convertReturnValue(final InstructionAdapter mv, final Class<?> returnType, final Type asmReturnType) {
+ switch(asmReturnType.getSort()) {
+ case Type.VOID:
+ mv.pop();
+ break;
+ case Type.BOOLEAN:
+ JSType.TO_BOOLEAN.invoke(mv);
+ break;
+ case Type.BYTE:
+ JSType.TO_INT32.invoke(mv);
+ mv.visitInsn(Opcodes.I2B);
+ break;
+ case Type.SHORT:
+ JSType.TO_INT32.invoke(mv);
+ mv.visitInsn(Opcodes.I2S);
+ break;
+ case Type.CHAR:
+ // JSType doesn't have a TO_CHAR, so we have services supply us one.
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "toCharPrimitive", TO_CHAR_PRIMITIVE_METHOD_DESCRIPTOR, false);
+ break;
+ case Type.INT:
+ JSType.TO_INT32.invoke(mv);
+ break;
+ case Type.LONG:
+ JSType.TO_LONG.invoke(mv);
+ break;
+ case Type.FLOAT:
+ JSType.TO_NUMBER.invoke(mv);
+ mv.visitInsn(Opcodes.D2F);
+ break;
+ case Type.DOUBLE:
+ JSType.TO_NUMBER.invoke(mv);
+ break;
+ default:
+ if(asmReturnType.equals(OBJECT_TYPE)) {
+ // Must hide ConsString (and potentially other internal Nashorn types) from callers
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "exportReturnValue", EXPORT_RETURN_VALUE_METHOD_DESCRIPTOR, false);
+ } else if(asmReturnType.equals(STRING_TYPE)){
+ // Well-known conversion to String. Not using the JSType one as we want to preserve null as null instead
+ // of the string "n,u,l,l".
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "toString", TO_STRING_METHOD_DESCRIPTOR, false);
+ } else {
+ // Invoke converter method handle for everything else. Note that we could have just added an asType or
+ // filterReturnValue to the invoked handle instead, but then every instance would have the function
+ // method handle wrapped in a separate converter method handle, making handle.invokeExact() megamorphic.
+ if(classOverride) {
+ mv.getstatic(generatedClassName, converterFields.get(returnType), METHOD_HANDLE_TYPE_DESCRIPTOR);
+ } else {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.getfield(generatedClassName, converterFields.get(returnType), METHOD_HANDLE_TYPE_DESCRIPTOR);
+ }
+ mv.swap();
+ emitInvokeExact(mv, MethodType.methodType(returnType, Object.class));
+ }
+ }
+ }
+
+ private static void emitInvokeExact(final InstructionAdapter mv, final MethodType type) {
+ mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
+ }
+
+ private static void boxStackTop(final InstructionAdapter mv, final Type t) {
+ switch(t.getSort()) {
+ case Type.BOOLEAN:
+ invokeValueOf(mv, "Boolean", 'Z');
+ break;
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ // bytes and shorts get boxed as integers
+ invokeValueOf(mv, "Integer", 'I');
+ break;
+ case Type.CHAR:
+ invokeValueOf(mv, "Character", 'C');
+ break;
+ case Type.FLOAT:
+ // floats get boxed as doubles
+ mv.visitInsn(Opcodes.F2D);
+ invokeValueOf(mv, "Double", 'D');
+ break;
+ case Type.LONG:
+ invokeValueOf(mv, "Long", 'J');
+ break;
+ case Type.DOUBLE:
+ invokeValueOf(mv, "Double", 'D');
+ break;
+ case Type.ARRAY:
+ case Type.METHOD:
+ // Already boxed
+ break;
+ case Type.OBJECT:
+ if(t.equals(OBJECT_TYPE)) {
+ mv.invokestatic(SCRIPTUTILS_TYPE_NAME, "unwrap", UNWRAP_METHOD_DESCRIPTOR, false);
+ }
+ break;
+ default:
+ // Not expecting anything else (e.g. VOID)
+ assert false;
+ break;
+ }
+ }
+
+ private static void invokeValueOf(final InstructionAdapter mv, final String boxedType, final char unboxedType) {
+ mv.invokestatic("java/lang/" + boxedType, "valueOf", "(" + unboxedType + ")Ljava/lang/" + boxedType + ";", false);
}
/**
@@ -805,7 +1013,7 @@ final class JavaAdapterBytecodeGenerator {
}
}
- private void generateSuperMethod(MethodInfo mi) {
+ private void generateSuperMethod(final MethodInfo mi) {
final Method method = mi.method;
final String methodDesc = mi.type.toMethodDescriptorString();
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
index 879d908c..77004978 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
@@ -30,25 +30,34 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import jdk.internal.dynalink.beans.StaticClass;
+import jdk.nashorn.internal.codegen.DumpBytecode;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
* It can be invoked repeatedly to create multiple adapter classes from the same bytecode; adapter classes that have
* class-level overrides must be re-created for every set of such overrides. Note that while this class is named
* "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this
- * class are normally created by {@link JavaAdapterBytecodeGenerator}.
+ * class are normally created by {@code JavaAdapterBytecodeGenerator}.
*/
-@SuppressWarnings("javadoc")
final class JavaAdapterClassLoader {
private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
+ private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
+ private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
+ Arrays.asList(JavaAdapterServices.class.getName(), ScriptObject.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
private final String className;
private final byte[] classBytes;
- JavaAdapterClassLoader(String className, byte[] classBytes) {
+ JavaAdapterClassLoader(final String className, final byte[] classBytes) {
this.className = className.replace('/', '.');
this.classBytes = classBytes;
}
@@ -94,7 +103,7 @@ final class JavaAdapterClassLoader {
// loaded by a loader that prevents package.access. If so, it'd throw
// SecurityException for nashorn's classes!. For adapter's to work, we
// should be able to refer to the few classes it needs in its implementation.
- if(ScriptFunction.class.getName().equals(name) || JavaAdapterServices.class.getName().equals(name)) {
+ if(VISIBLE_INTERNAL_CLASS_NAMES.contains(name)) {
return myLoader.loadClass(name);
}
throw se;
@@ -105,6 +114,14 @@ final class JavaAdapterClassLoader {
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if(name.equals(className)) {
assert classBytes != null : "what? already cleared .class bytes!!";
+
+ final Context ctx = AccessController.doPrivileged(new PrivilegedAction<Context>() {
+ @Override
+ public Context run() {
+ return Context.getContext();
+ }
+ }, GET_CONTEXT_ACC_CTXT);
+ DumpBytecode.dumpBytecode(ctx.getEnv(), ctx.getLogger(jdk.nashorn.internal.codegen.Compiler.class), classBytes, name);
return defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
}
throw new ClassNotFoundException(name);
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 1b5345b0..40ea01ae 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -113,15 +113,15 @@ public final class JavaAdapterFactory {
* @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is
* final, non-public, or has no public or protected constructors.
*/
- public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
+ public static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
}
- private static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
+ private static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
assert types != null && types.length > 0;
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- for (Class<?> type : types) {
+ for (final Class<?> type : types) {
// check for restricted package access
Context.checkPackageAccess(type);
// check for classes, interfaces in reflection
@@ -163,7 +163,7 @@ public final class JavaAdapterFactory {
final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup);
return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(
NashornCallSiteDescriptor.get(lookup, "dyn:new",
- MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false,
+ MethodType.methodType(targetType, StaticClass.class, sourceType), 0), null, 0, false,
adapterClass, null)).getInvocation(), adapterClass);
}
@@ -257,7 +257,7 @@ public final class JavaAdapterFactory {
final boolean autoConvertibleFromFunction;
final AdaptationResult adaptationResult;
- AdapterInfo(Class<?> superClass, List<Class<?>> interfaces, ClassAndLoader definingLoader) throws AdaptationException {
+ AdapterInfo(final Class<?> superClass, final List<Class<?>> interfaces, final ClassAndLoader definingLoader) throws AdaptationException {
this.commonLoader = findCommonLoader(definingLoader);
final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false);
this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction();
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
index 4cb8cfa7..08e46821 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
@@ -150,7 +150,7 @@ public final class JavaAdapterServices {
return Context.getGlobal();
}
- static void setClassOverrides(ScriptObject overrides) {
+ static void setClassOverrides(final ScriptObject overrides) {
classOverrides.set(overrides);
}
@@ -183,7 +183,7 @@ public final class JavaAdapterServices {
public ClassLoader run() {
return new SecureClassLoader(null) {
@Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
+ protected Class<?> findClass(final String name) throws ClassNotFoundException {
if(name.equals(className)) {
return defineClass(name, bytes, 0, bytes.length, new ProtectionDomain(
new CodeSource(null, (CodeSigner[])null), new Permissions()));
@@ -197,8 +197,49 @@ public final class JavaAdapterServices {
try {
return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke",
MethodType.methodType(void.class, MethodHandle.class, Object.class));
- } catch(ReflectiveOperationException e) {
+ } catch(final ReflectiveOperationException e) {
throw new AssertionError(e.getMessage(), e);
}
}
+
+ /**
+ * Returns a method handle used to convert a return value from a delegate method (always Object) to the expected
+ * Java return type.
+ * @param returnType the return type
+ * @return the converter for the expected return type
+ */
+ public static MethodHandle getObjectConverter(final Class<?> returnType) {
+ return Bootstrap.getLinkerServices().getTypeConverter(Object.class, returnType);
+ }
+
+ /**
+ * Invoked when returning Object from an adapted method to filter out internal Nashorn objects that must not be seen
+ * by the callers. Currently only transforms {@code ConsString} into {@code String} and transforms {@code ScriptObject} into {@code ScriptObjectMirror}.
+ * @param obj the return value
+ * @return the filtered return value.
+ */
+ public static Object exportReturnValue(final Object obj) {
+ return NashornBeansLinker.exportArgument(obj, true);
+ }
+
+ /**
+ * Invoked to convert a return value of a delegate function to primitive char. There's no suitable conversion in
+ * {@code JSType}, so we provide our own to adapters.
+ * @param obj the return value.
+ * @return the character value of the return value
+ */
+ public static char toCharPrimitive(final Object obj) {
+ return JavaArgumentConverters.toCharPrimitive(obj);
+ }
+
+ /**
+ * Invoked to convert a return value of a delegate function to String. It is similar to
+ * {@code JSType.toString(Object)}, except it doesn't handle StaticClass specially, and it returns null for null
+ * input instead of the string "null".
+ * @param obj the return value.
+ * @return the String value of the return value
+ */
+ public static String toString(final Object obj) {
+ return JavaArgumentConverters.toString(obj);
+ }
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
index 984d0f41..8b085e4c 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
@@ -124,34 +124,14 @@ final class JavaArgumentConverters {
return s.charAt(0);
}
- @SuppressWarnings("unused")
- private static char toCharPrimitive(final Object obj0) {
+ static char toCharPrimitive(final Object obj0) {
final Character c = toChar(obj0);
return c == null ? (char)0 : c;
}
- // Almost identical to ScriptRuntime.toString, but doesn't handle StaticClass specially, and it returns null for
- // null instead of the string "null".
- private static String toString(final Object obj0) {
- for (Object obj = obj0; ;) {
- if (obj == null) {
- return null;
- } else if (obj instanceof String) {
- return (String) obj;
- } else if (obj instanceof ConsString) {
- return obj.toString();
- } else if (obj instanceof Number) {
- return JSType.toString(((Number)obj).doubleValue());
- } else if (obj instanceof Boolean) {
- return ((Boolean) obj).toString();
- } else if (obj == UNDEFINED) {
- return "undefined";
- } else if (obj instanceof ScriptObject) {
- obj = JSType.toPrimitive(obj, String.class);
- continue;
- }
- throw assertUnexpectedType(obj);
- }
+ // Almost identical to ScriptRuntime.toString, but returns null for null instead of the string "null".
+ static String toString(final Object obj) {
+ return obj == null ? null : JSType.toString(obj);
}
@SuppressWarnings("unused")
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
index a4af3184..3c7fcb26 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
@@ -27,7 +27,7 @@ package jdk.nashorn.internal.runtime.linker;
/**
* Represents a an adapter for invoking superclass methods on an adapter instance generated by
- * {@link JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
+ * {@code JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
* without any behavior. All the behavior is defined in the {@code JavaSuperAdapterLinker}.
*/
class JavaSuperAdapter {
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
index c42af1d8..9aeefd72 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
@@ -42,7 +42,7 @@ import jdk.internal.dynalink.support.Lookup;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
- * A linker for instances of {@link JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
+ * A linker for instances of {@code JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
* bean linker for the adapter class and prepending {@code super$} to method names.
*
*/
@@ -115,15 +115,15 @@ final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
final MethodHandle invocation = guardedInv.getInvocation();
final MethodType invType = invocation.type();
- // For invocation typed R(T0, ...) create a dynamic method binder of type R(R, T0)
- final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(invType.returnType(),
+ // For invocation typed R(T0, ...) create a dynamic method binder of type Object(R, T0)
+ final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(Object.class,
invType.returnType(), invType.parameterType(0)));
- // For invocation typed R(T0, T1, ...) create a dynamic method binder of type R(R, T0, T1, ...)
+ // For invocation typed R(T0, T1, ...) create a dynamic method binder of type Object(R, T0, T1, ...)
final MethodHandle droppingBinder = MethodHandles.dropArguments(typedBinder, 2,
invType.parameterList().subList(1, invType.parameterCount()));
// Finally, fold the invocation into the binder to produce a method handle that will bind every returned
// DynamicMethod object from dyn:getMethod calls to the actual receiver
- // R(R(T0, T1, ...), T0, T1, ...)
+ // Object(R(T0, T1, ...), T0, T1, ...)
final MethodHandle bindingInvocation = MethodHandles.foldArguments(droppingBinder, invocation);
final MethodHandle typedGetAdapter = asFilterType(GET_ADAPTER, 0, invType, type);
@@ -147,7 +147,7 @@ final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
* @param sourceType the source method type for filtering
* @return a type adapted filter
*/
- private static MethodHandle asFilterType(final MethodHandle filter, int pos, MethodType targetType, MethodType sourceType) {
+ private static MethodHandle asFilterType(final MethodHandle filter, final int pos, final MethodType targetType, final MethodType sourceType) {
return filter.asType(MethodType.methodType(targetType.parameterType(pos), sourceType.parameterType(pos)));
}
@@ -165,7 +165,7 @@ final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
*/
@SuppressWarnings("unused")
private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
- return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindDynamicMethod(dynamicMethod, boundThis);
+ return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindCallable(dynamicMethod, boundThis, null);
}
/**
@@ -175,7 +175,7 @@ final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
* @return true if the receiver is a super adapter, and its underlying adapter is of the specified class
*/
@SuppressWarnings("unused")
- private static boolean isAdapterOfClass(Class<?> clazz, Object obj) {
+ private static boolean isAdapterOfClass(final Class<?> clazz, final Object obj) {
return obj instanceof JavaSuperAdapter && clazz == (((JavaSuperAdapter)obj).getAdapter()).getClass();
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
index 882c65dd..46324db4 100644
--- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
+++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
@@ -46,7 +46,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import jdk.internal.dynalink.ChainedCallSite;
import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -63,7 +62,10 @@ public class LinkerCallSite extends ChainedCallSite {
private static final String PROFILEFILE = Options.getStringProperty("nashorn.profilefile", "NashornProfile.txt");
- private static final MethodHandle INCREASE_MISS_COUNTER = findOwnMH("increaseMissCount", Object.class, String.class, Object.class);
+ private static final MethodHandle INCREASE_MISS_COUNTER = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "increaseMissCount", MH.type(Object.class, String.class, Object.class));
+ private static final MethodHandle ON_CATCH_INVALIDATION = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "onCatchInvalidation", MH.type(ChainedCallSite.class, LinkerCallSite.class));
+
+ private int catchInvalidations;
LinkerCallSite(final NashornCallSiteDescriptor descriptor) {
super(descriptor);
@@ -72,6 +74,34 @@ public class LinkerCallSite extends ChainedCallSite {
}
}
+ @Override
+ protected MethodHandle getPruneCatches() {
+ return MH.filterArguments(super.getPruneCatches(), 0, ON_CATCH_INVALIDATION);
+ }
+
+ /**
+ * Action to perform when a catch guard around a callsite triggers. Increases
+ * catch invalidation counter
+ * @param callSite callsite
+ * @return the callsite, so this can be used as argument filter
+ */
+ @SuppressWarnings("unused")
+ private static ChainedCallSite onCatchInvalidation(final LinkerCallSite callSite) {
+ ++callSite.catchInvalidations;
+ return callSite;
+ }
+
+ /**
+ * Get the number of catch invalidations that have happened at this call site so far
+ * @param callSiteToken call site token, unique to the callsite.
+ * @return number of catch invalidations, i.e. thrown exceptions caught by the linker
+ */
+ public static int getCatchInvalidationCount(final Object callSiteToken) {
+ if (callSiteToken instanceof LinkerCallSite) {
+ return ((LinkerCallSite)callSiteToken).catchInvalidations;
+ }
+ return 0;
+ }
/**
* Construct a new linker call site.
* @param name Name of method.
@@ -79,8 +109,7 @@ public class LinkerCallSite extends ChainedCallSite {
* @param flags Call site specific flags.
* @return New LinkerCallSite.
*/
- static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type,
- final int flags) {
+ static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int flags) {
final NashornCallSiteDescriptor desc = NashornCallSiteDescriptor.get(lookup, name, type, flags);
if (desc.isProfile()) {
@@ -145,11 +174,10 @@ public class LinkerCallSite extends ChainedCallSite {
*/
public static Object increaseMissCount(final String desc, final Object self) {
++missCount;
- if(r.nextInt(100) < missSamplingPercentage) {
- AtomicInteger i = missCounts.get(desc);
- if(i == null) {
- i = new AtomicInteger(1);
- missCounts.put(desc, i);
+ if (r.nextInt(100) < missSamplingPercentage) {
+ final AtomicInteger i = missCounts.get(desc);
+ if (i == null) {
+ missCounts.put(desc, new AtomicInteger(1));
} else {
i.incrementAndGet();
}
@@ -157,14 +185,6 @@ public class LinkerCallSite extends ChainedCallSite {
return self;
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- try {
- return MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, name, MH.type(rtype, types));
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), LinkerCallSite.class, name, MH.type(rtype, types));
- }
- }
-
/*
* Debugging call sites.
*/
@@ -276,7 +296,6 @@ public class LinkerCallSite extends ChainedCallSite {
}
static class ProfileDumper implements Runnable {
- @SuppressWarnings("resource")
@Override
public void run() {
PrintWriter out = null;
@@ -314,10 +333,11 @@ public class LinkerCallSite extends ChainedCallSite {
* Debug subclass for LinkerCallSite that allows tracing
*/
private static class TracingLinkerCallSite extends LinkerCallSite {
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
- private static final MethodHandle TRACEOBJECT = findOwnMH("traceObject", Object.class, MethodHandle.class, Object[].class);
- private static final MethodHandle TRACEVOID = findOwnMH("traceVoid", void.class, MethodHandle.class, Object[].class);
- private static final MethodHandle TRACEMISS = findOwnMH("traceMiss", void.class, String.class, Object[].class);
+ private static final MethodHandle TRACEOBJECT = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceObject", MH.type(Object.class, MethodHandle.class, Object[].class));
+ private static final MethodHandle TRACEVOID = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceVoid", MH.type(void.class, MethodHandle.class, Object[].class));
+ private static final MethodHandle TRACEMISS = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceMiss", MH.type(void.class, String.class, Object[].class));
TracingLinkerCallSite(final NashornCallSiteDescriptor desc) {
super(desc);
@@ -420,7 +440,7 @@ public class LinkerCallSite extends ChainedCallSite {
final Object arg = args[i];
out.print(", ");
- if (getNashornDescriptor().isTraceScope() || !(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
+ if (!(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
printObject(out, arg);
} else {
out.print("SCOPE");
@@ -448,7 +468,7 @@ public class LinkerCallSite extends ChainedCallSite {
*
* @throws Throwable if invocation fails or throws exception/error
*/
- @SuppressWarnings({"unused", "resource"})
+ @SuppressWarnings("unused")
public Object traceObject(final MethodHandle mh, final Object... args) throws Throwable {
final PrintWriter out = Context.getCurrentErr();
tracePrint(out, "ENTER ", args, null);
@@ -466,7 +486,7 @@ public class LinkerCallSite extends ChainedCallSite {
*
* @throws Throwable if invocation fails or throws exception/error
*/
- @SuppressWarnings({"unused", "resource"})
+ @SuppressWarnings("unused")
public void traceVoid(final MethodHandle mh, final Object... args) throws Throwable {
final PrintWriter out = Context.getCurrentErr();
tracePrint(out, "ENTER ", args, null);
@@ -486,14 +506,6 @@ public class LinkerCallSite extends ChainedCallSite {
public void traceMiss(final String desc, final Object... args) throws Throwable {
tracePrint(Context.getCurrentErr(), desc, args, null);
}
-
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- try {
- return MH.findStatic(MethodHandles.lookup(), TracingLinkerCallSite.class, name, MH.type(rtype, types));
- } catch (final MethodHandleFactory.LookupException e) {
- return MH.findVirtual(MethodHandles.lookup(), TracingLinkerCallSite.class, name, MH.type(rtype, types));
- }
- }
}
// counters updated in debug mode
@@ -503,6 +515,11 @@ public class LinkerCallSite extends ChainedCallSite {
private static final Random r = new Random();
private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1);
+ @Override
+ protected int getMaxChainLength() {
+ return 8;
+ }
+
/**
* Get the callsite count
* @return the count
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
index e2db2b11..d5133cb3 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
@@ -35,22 +35,52 @@ import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Lookup;
+import jdk.nashorn.api.scripting.ScriptUtils;
+import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified
* {@code asType} method that will ensure that we never pass internal engine objects that should not be externally
- * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add
+ * observable (currently ConsString and ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add
* this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
* the target method handle parameter signature is {@code Object}.
*/
public class NashornBeansLinker implements GuardingDynamicLinker {
- private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class);
+ // System property to control whether to wrap ScriptObject->ScriptObjectMirror for
+ // Object type arguments of Java method calls, field set and array set.
+ private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
+
+ private static final MethodHandle EXPORT_ARGUMENT;
+ private static final MethodHandle EXPORT_NATIVE_ARRAY;
+ private static final MethodHandle EXPORT_SCRIPT_OBJECT;
+ private static final MethodHandle IMPORT_RESULT;
+ private static final MethodHandle FILTER_CONSSTRING;
+
+ static {
+ final Lookup lookup = new Lookup(MethodHandles.lookup());
+ EXPORT_ARGUMENT = lookup.findOwnStatic("exportArgument", Object.class, Object.class);
+ EXPORT_NATIVE_ARRAY = lookup.findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
+ EXPORT_SCRIPT_OBJECT = lookup.findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
+ IMPORT_RESULT = lookup.findOwnStatic("importResult", Object.class, Object.class);
+ FILTER_CONSSTRING = lookup.findOwnStatic("consStringFilter", Object.class, Object.class);
+ }
private final BeansLinker beansLinker = new BeansLinker();
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
+ if (linkRequest.getReceiver() instanceof ConsString) {
+ // In order to treat ConsString like a java.lang.String we need a link request with a string receiver.
+ final Object[] arguments = linkRequest.getArguments();
+ arguments[0] = "";
+ final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(linkRequest.getCallSiteDescriptor(), arguments);
+ final GuardedInvocation invocation = getGuardedInvocation(beansLinker, forgedLinkRequest, linkerServices);
+ // If an invocation is found we add a filter that makes it work for both Strings and ConsStrings.
+ return invocation == null ? null : invocation.filterArguments(0, FILTER_CONSSTRING);
+ }
return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
}
@@ -69,6 +99,41 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
@SuppressWarnings("unused")
private static Object exportArgument(final Object arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportNativeArray(final NativeArray arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportScriptObject(final ScriptObject arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object exportScriptArray(final NativeArray arg) {
+ return exportArgument(arg, MIRROR_ALWAYS);
+ }
+
+ static Object exportArgument(final Object arg, final boolean mirrorAlways) {
+ if (arg instanceof ConsString) {
+ return arg.toString();
+ } else if (mirrorAlways && arg instanceof ScriptObject) {
+ return ScriptUtils.wrap((ScriptObject)arg);
+ } else {
+ return arg;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private static Object importResult(final Object arg) {
+ return ScriptUtils.unwrap(arg);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object consStringFilter(final Object arg) {
return arg instanceof ConsString ? arg.toString() : arg;
}
@@ -81,30 +146,58 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
@Override
public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
- final MethodHandle typed = linkerServices.asType(handle, fromType);
-
final MethodType handleType = handle.type();
final int paramCount = handleType.parameterCount();
assert fromType.parameterCount() == handleType.parameterCount();
+ MethodType newFromType = fromType;
MethodHandle[] filters = null;
for(int i = 0; i < paramCount; ++i) {
- if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) {
- if(filters == null) {
+ final MethodHandle filter = argConversionFilter(handleType.parameterType(i), fromType.parameterType(i));
+ if (filter != null) {
+ if (filters == null) {
filters = new MethodHandle[paramCount];
}
- filters[i] = EXPORT_ARGUMENT;
+ // "erase" specific type with Object type or else we'll get filter mismatch
+ newFromType = newFromType.changeParameterType(i, Object.class);
+ filters[i] = filter;
}
}
- return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
+ final MethodHandle typed = linkerServices.asType(handle, newFromType);
+ MethodHandle result = filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
+ // Filter Object typed return value for possible ScriptObjectMirror. We convert
+ // ScriptObjectMirror as ScriptObject (if it is mirror from current global).
+ if (MIRROR_ALWAYS && areBothObjects(handleType.returnType(), fromType.returnType())) {
+ result = MethodHandles.filterReturnValue(result, IMPORT_RESULT);
+ }
+
+ return result;
}
- private static boolean shouldConvert(final Class<?> handleType, final Class<?> fromType) {
+ private static MethodHandle argConversionFilter(final Class<?> handleType, final Class<?> fromType) {
+ if (handleType == Object.class) {
+ if (fromType == Object.class) {
+ return EXPORT_ARGUMENT;
+ } else if (fromType == NativeArray.class) {
+ return EXPORT_NATIVE_ARRAY;
+ } else if (fromType == ScriptObject.class) {
+ return EXPORT_SCRIPT_OBJECT;
+ }
+ }
+ return null;
+ }
+
+ private static boolean areBothObjects(final Class<?> handleType, final Class<?> fromType) {
return handleType == Object.class && fromType == Object.class;
}
@Override
+ public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
+ return Implementation.asTypeLosslessReturn(this, handle, fromType);
+ }
+
+ @Override
public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
return linkerServices.getTypeConverter(sourceType, targetType);
}
@@ -121,6 +214,15 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
@Override
public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+ if (sourceType == ConsString.class) {
+ if (String.class == targetType1 || CharSequence.class == targetType1) {
+ return Comparison.TYPE_1_BETTER;
+ }
+
+ if (String.class == targetType2 || CharSequence.class == targetType2) {
+ return Comparison.TYPE_2_BETTER;
+ }
+ }
return linkerServices.compareConversion(sourceType, targetType1, targetType2);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
index 88ccf5a4..4ed6e3a2 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
@@ -44,9 +44,11 @@ import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* Nashorn bottom linker; used as a last-resort catch-all linker for all linking requests that fall through all other
@@ -104,10 +106,13 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
if (callType.parameterCount() != m.getParameterCount() + 2) {
throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
}
- return new GuardedInvocation(
+ return Bootstrap.asTypeSafeReturn(new GuardedInvocation(
// drop 'thiz' passed from the script.
MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
- Guards.getInstanceOfGuard(m.getDeclaringClass())).asType(callType);
+ Guards.getInstanceOfGuard(m.getDeclaringClass())), linkerServices, desc);
+ }
+ if(BeansLinker.isDynamicConstructor(self)) {
+ throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
}
if(BeansLinker.isDynamicMethod(self)) {
throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
@@ -118,16 +123,24 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
case "getProp":
case "getElem":
+ if(NashornCallSiteDescriptor.isOptimistic(desc)) {
+ throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
+ }
if (desc.getOperand() != null) {
return getInvocation(EMPTY_PROP_GETTER, self, linkerServices, desc);
}
return getInvocation(EMPTY_ELEM_GETTER, self, linkerServices, desc);
case "setProp":
- case "setElem":
+ case "setElem": {
+ final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
+ if (strict) {
+ throw typeError("cant.set.property", getArgument(linkRequest), ScriptRuntime.safeToString(self));
+ }
if (desc.getOperand() != null) {
return getInvocation(EMPTY_PROP_SETTER, self, linkerServices, desc);
}
return getInvocation(EMPTY_ELEM_SETTER, self, linkerServices, desc);
+ }
default:
break;
}
@@ -151,14 +164,14 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
private static GuardedInvocation convertToTypeNoCast(final Class<?> sourceType, final Class<?> targetType) throws Exception {
final MethodHandle mh = CONVERTERS.get(targetType);
if (mh != null) {
- return new GuardedInvocation(mh, null);
+ return new GuardedInvocation(mh);
}
return null;
}
private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
- return Bootstrap.asType(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
+ return Bootstrap.asTypeSafeReturn(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
}
// Used solely in an assertion to figure out if the object we get here is something we in fact expect. Objects
@@ -218,7 +231,7 @@ final class NashornBottomLinker implements GuardingDynamicLinker, GuardingTypeCo
return null;
}
- for (Class<?> iface : clazz.getInterfaces()) {
+ for (final Class<?> iface : clazz.getInterfaces()) {
// check accessiblity up-front
if (! Context.isAccessibleClass(iface)) {
continue;
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
index 0c2c4d5b..27fc3a2e 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
@@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentMap;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.internal.ir.debug.NashornTextifier;
/**
* Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@@ -42,40 +43,63 @@ import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor {
/** Flags that the call site references a scope variable (it's an identifier reference or a var declaration, not a
* property access expression. */
- public static final int CALLSITE_SCOPE = 0x01;
+ public static final int CALLSITE_SCOPE = 1 << 0;
/** Flags that the call site is in code that uses ECMAScript strict mode. */
- public static final int CALLSITE_STRICT = 0x02;
+ public static final int CALLSITE_STRICT = 1 << 1;
/** Flags that a property getter or setter call site references a scope variable that is located at a known distance
* in the scope chain. Such getters and setters can often be linked more optimally using these assumptions. */
- public static final int CALLSITE_FAST_SCOPE = 0x400;
+ public static final int CALLSITE_FAST_SCOPE = 1 << 2;
+ /** Flags that a callsite type is optimistic, i.e. we might get back a wider return value than encoded in the
+ * descriptor, and in that case we have to throw an UnwarrantedOptimismException */
+ public static final int CALLSITE_OPTIMISTIC = 1 << 3;
+ /** Is this really an apply that we try to call as a call? */
+ public static final int CALLSITE_APPLY_TO_CALL = 1 << 4;
+ /** Does this a callsite for a variable declaration? */
+ public static final int CALLSITE_DECLARE = 1 << 5;
/** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit
* code where call sites have this flag set. */
- public static final int CALLSITE_PROFILE = 0x10;
+ public static final int CALLSITE_PROFILE = 1 << 6;
/** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where
* call sites have this flag set. */
- public static final int CALLSITE_TRACE = 0x20;
+ public static final int CALLSITE_TRACE = 1 << 7;
/** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword
* {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
- public static final int CALLSITE_TRACE_MISSES = 0x40;
+ public static final int CALLSITE_TRACE_MISSES = 1 << 8;
/** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword
- * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag
- * set. */
- public static final int CALLSITE_TRACE_ENTEREXIT = 0x80;
+ * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
+ public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 9;
/** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts
* that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites
* have this flag set. */
- public static final int CALLSITE_TRACE_VALUES = 0x100;
- /** Ordinarily, when {@link #CALLSITE_TRACE_VALUES} is set, scope objects are not printed in the trace but instead
- * the word {@code "SCOPE"} is printed instead With this flag, scope objects are also printed. Contexts that have
- * the keyword {@code "scope"} in their {@code "trace.callsites"} property emit code where call sites have this flag
- * set. */
- public static final int CALLSITE_TRACE_SCOPE = 0x200;
+ public static final int CALLSITE_TRACE_VALUES = 1 << 10;
+
+ //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious
+ //right now given the program points
+
+ /**
+ * Number of bits the program point is shifted to the left in the flags (lowest bit containing a program point).
+ * Always one larger than the largest flag shift. Note that introducing a new flag halves the number of program
+ * points we can have.
+ * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its
+ * trace/profile settings.
+ */
+ public static final int CALLSITE_PROGRAM_POINT_SHIFT = 11;
+
+ /**
+ * Maximum program point value. 21 bits should be enough for anyone
+ */
+ public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1;
+
+ /**
+ * Flag mask to get the program point flags
+ */
+ public static final int FLAGS_MASK = (1 << CALLSITE_PROGRAM_POINT_SHIFT) - 1;
private static final ClassValue<ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor>> canonicals =
new ClassValue<ConcurrentMap<NashornCallSiteDescriptor,NashornCallSiteDescriptor>>() {
@Override
- protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(Class<?> type) {
+ protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(final Class<?> type) {
return new ConcurrentHashMap<>();
}
};
@@ -87,6 +111,34 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
private final int flags;
/**
+ * Function used by {@link NashornTextifier} to represent call site flags in
+ * human readable form
+ * @param flags call site flags
+ * @return human readable form of this callsite descriptor
+ */
+ public static String toString(final int flags) {
+ final StringBuilder sb = new StringBuilder();
+ if ((flags & CALLSITE_SCOPE) != 0) {
+ if ((flags & CALLSITE_FAST_SCOPE) != 0) {
+ sb.append("fastscope ");
+ } else {
+ assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
+ sb.append("scope ");
+ }
+ if ((flags & CALLSITE_DECLARE) != 0) {
+ sb.append("declare ");
+ }
+ }
+ if ((flags & CALLSITE_APPLY_TO_CALL) != 0) {
+ sb.append("apply2call ");
+ }
+ if ((flags & CALLSITE_STRICT) != 0) {
+ sb.append("strict ");
+ }
+ return sb.length() == 0 ? "" : " " + sb.toString().trim();
+ }
+
+ /**
* Retrieves a Nashorn call site descriptor with the specified values. Since call site descriptors are immutable
* this method is at liberty to retrieve canonicalized instances (although it is not guaranteed it will do so).
* @param lookup the lookup describing the script
@@ -203,7 +255,7 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
* @return the Nashorn-specific flags for the call site, or 0 if the passed descriptor is not a Nashorn call site
* descriptor.
*/
- private static int getFlags(final CallSiteDescriptor desc) {
+ public static int getFlags(final CallSiteDescriptor desc) {
return desc instanceof NashornCallSiteDescriptor ? ((NashornCallSiteDescriptor)desc).flags : 0;
}
@@ -262,6 +314,62 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
return isFlag(desc, CALLSITE_STRICT);
}
+ /**
+ * Returns true if this is an apply call that we try to call as
+ * a "call"
+ * @param desc descriptor
+ * @return true if apply to call
+ */
+ public static boolean isApplyToCall(final CallSiteDescriptor desc) {
+ return isFlag(desc, CALLSITE_APPLY_TO_CALL);
+ }
+
+ /**
+ * Is this an optimistic call site
+ * @param desc descriptor
+ * @return true if optimistic
+ */
+ public static boolean isOptimistic(final CallSiteDescriptor desc) {
+ return isFlag(desc, CALLSITE_OPTIMISTIC);
+ }
+
+ /**
+ * Does this callsite contain a declaration for its target?
+ * @param desc descriptor
+ * @return true if contains declaration
+ */
+ public static boolean isDeclaration(final CallSiteDescriptor desc) {
+ return isFlag(desc, CALLSITE_DECLARE);
+ }
+
+ /**
+ * Returns true if {@code flags} has the {@link #CALLSITE_STRICT} bit set.
+ * @param flags the flags
+ * @return true if the flag is set, false otherwise.
+ */
+ public static boolean isStrictFlag(final int flags) {
+ return (flags & CALLSITE_STRICT) != 0;
+ }
+
+ /**
+ * Returns true if {@code flags} has the {@link #CALLSITE_SCOPE} bit set.
+ * @param flags the flags
+ * @return true if the flag is set, false otherwise.
+ */
+ public static boolean isScopeFlag(final int flags) {
+ return (flags & CALLSITE_SCOPE) != 0;
+ }
+
+ /**
+ * Get a program point from a descriptor (must be optimistic)
+ * @param desc descriptor
+ * @return program point
+ */
+ public static int getProgramPoint(final CallSiteDescriptor desc) {
+ assert isOptimistic(desc) : "program point requested from non-optimistic descriptor " + desc;
+ return getFlags(desc) >> CALLSITE_PROGRAM_POINT_SHIFT;
+ }
+
boolean isProfile() {
return isFlag(CALLSITE_PROFILE);
}
@@ -282,12 +390,13 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
return isFlag(CALLSITE_TRACE_VALUES);
}
- boolean isTraceScope() {
- return isFlag(CALLSITE_TRACE_SCOPE);
+ boolean isOptimistic() {
+ return isFlag(CALLSITE_OPTIMISTIC);
}
@Override
public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return get(getLookup(), operator, operand, newMethodType, flags);
}
+
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
index 77c5e93c..dac36d4a 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
@@ -31,6 +31,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.ref.WeakReference;
import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.objects.Global;
@@ -38,56 +39,80 @@ import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.options.Options;
/**
* Constructor of method handles used to guard call sites.
*/
public final class NashornGuards {
- private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
- private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class);
- private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
- private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+ private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, ScriptObject.class, PropertyMap.class);
+ private static final MethodHandle IS_MAP_SCRIPTOBJECT = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+ private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+ private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
+ private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class);
private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
- private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+ //TODO - maybe put this back in ScriptFunction instead of the ClassCastException.class relinkage
+ //private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
+
+ private static final boolean CCE_ONLY = Options.getBooleanProperty("nashorn.cce");
// don't create me!
private NashornGuards() {
}
/**
- * Get the guard that checks if an item is a {@code ScriptObject}
- * @return method handle for guard
+ * Given a callsite descriptor and a link request, determine whether we should use an instanceof
+ * check explicitly for the guard if needed, or if we should link it with a try/catch ClassCastException
+ * combinator as its relink criteria - i.e. relink when CCE is thrown.
+ *
+ * @param desc callsite descriptor
+ * @param request link request
+ * @return true of explicit instanceof check is needed
*/
- public static MethodHandle getScriptObjectGuard() {
- return IS_SCRIPTOBJECT;
+ public static boolean explicitInstanceOfCheck(final CallSiteDescriptor desc, final LinkRequest request) {
+ //THIS is currently true, as the inliner encounters several problems with sun.misc.ValueConversions.castReference
+ //otherwise. We should only use the exception based relink where we have no choice, and the result is faster code,
+ //for example in the NativeArray, TypedArray, ContinuousArray getters. For the standard callsite, it appears that
+ //we lose performance rather than gain it, due to JVM issues. :-(
+ return !CCE_ONLY;
}
/**
- * Get the guard that checks if an item is not a {@code JSObject}
- * @return method handle for guard
+ * Returns a guard that does an instanceof ScriptObject check on the receiver
+ * @return guard
*/
- public static MethodHandle getNotJSObjectGuard() {
- return IS_NOT_JSOBJECT;
+ public static MethodHandle getScriptObjectGuard() {
+ return IS_SCRIPTOBJECT;
}
+ /**
+ * Get the guard that checks if an item is not a {@code JSObject}
+ * @return method handle for guard
+ */
+ public static MethodHandle getNotJSObjectGuard() {
+ return IS_NOT_JSOBJECT;
+ }
+
/**
- * Get the guard that checks if an item is a {@code ScriptFunction}
- * @return method handle for guard
+ * Returns a guard that does an instanceof ScriptObject check on the receiver
+ * @param explicitInstanceOfCheck - if false, then this is a nop, because it's all the guard does
+ * @return guard
*/
- public static MethodHandle getScriptFunctionGuard() {
- return IS_SCRIPTFUNCTION;
+ public static MethodHandle getScriptObjectGuard(final boolean explicitInstanceOfCheck) {
+ return explicitInstanceOfCheck ? IS_SCRIPTOBJECT : null;
}
/**
* Get the guard that checks if a {@link PropertyMap} is equal to
* a known map, using reference comparison
*
+ * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting
* @param map The map to check against. This will be bound to the guard method handle
*
* @return method handle for guard
*/
- public static MethodHandle getMapGuard(final PropertyMap map) {
- return MH.insertArguments(IS_MAP, 1, map);
+ public static MethodHandle getMapGuard(final PropertyMap map, final boolean explicitInstanceOfCheck) {
+ return MH.insertArguments(explicitInstanceOfCheck ? IS_MAP_SCRIPTOBJECT : IS_MAP, 1, map);
}
/**
@@ -109,23 +134,24 @@ public final class NashornGuards {
* @param sobj the first object in the prototype chain
* @param property the property
* @param desc the callsite descriptor
+ * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting
* @return method handle for guard
*/
- public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc) {
+ public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) {
if (!needsGuard(property, desc)) {
return null;
}
if (NashornCallSiteDescriptor.isScope(desc)) {
- if (property != null && property.isBound()) {
+ if (property != null && property.isBound() && !property.canChangeType()) {
// This is a declared top level variables in main script or eval, use identity guard.
return getIdentityGuard(sobj);
}
if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) {
// Undeclared variables in nested evals need stronger guards
- return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap()));
+ return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap(), explicitInstanceOfCheck));
}
}
- return getMapGuard(sobj.getMap());
+ return getMapGuard(sobj.getMap(), explicitInstanceOfCheck);
}
@@ -158,7 +184,13 @@ public final class NashornGuards {
* @return true if both guard1 and guard2 returned true
*/
public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) {
- return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+ if (guard1 == null) {
+ return guard2;
+ } else if (guard2 == null) {
+ return guard1;
+ } else {
+ return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+ }
}
@SuppressWarnings("unused")
@@ -167,13 +199,18 @@ public final class NashornGuards {
}
@SuppressWarnings("unused")
- private static boolean isNotJSObject(final Object self) {
- return !(self instanceof JSObject);
+ private static boolean isScriptObject(final Class<? extends ScriptObject> clazz, final Object self) {
+ return clazz.isInstance(self);
}
@SuppressWarnings("unused")
- private static boolean isScriptFunction(final Object self) {
- return self instanceof ScriptFunction;
+ private static boolean isMap(final ScriptObject self, final PropertyMap map) {
+ return self.getMap() == map;
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean isNotJSObject(final Object self) {
+ return !(self instanceof JSObject);
}
@SuppressWarnings("unused")
@@ -181,6 +218,7 @@ public final class NashornGuards {
return self instanceof ScriptObject && ((ScriptObject)self).getMap() == map;
}
+
@SuppressWarnings("unused")
private static boolean sameObject(final Object self, final WeakReference<ScriptObject> ref) {
return self == ref.get();
@@ -191,8 +229,12 @@ public final class NashornGuards {
return class1.isInstance(self) || class2.isInstance(self);
}
+ @SuppressWarnings("unused")
+ private static boolean isScriptFunction(final Object self) {
+ return self instanceof ScriptFunction;
+ }
+
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), NashornGuards.class, name, MH.type(rtype, types));
}
-
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
index 0ac5f9a5..75af367f 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
@@ -63,7 +63,7 @@ import jdk.nashorn.internal.runtime.Undefined;
final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
private static final ClassValue<MethodHandle> ARRAY_CONVERTERS = new ClassValue<MethodHandle>() {
@Override
- protected MethodHandle computeValue(Class<?> type) {
+ protected MethodHandle computeValue(final Class<?> type) {
return createArrayConverter(type);
}
};
@@ -91,16 +91,20 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
return null;
}
+ return Bootstrap.asTypeSafeReturn(getGuardedInvocation(self, request, desc), linkerServices, desc);
+ }
+
+ private static GuardedInvocation getGuardedInvocation(final Object self, final LinkRequest request, final CallSiteDescriptor desc) {
final GuardedInvocation inv;
if (self instanceof ScriptObject) {
inv = ((ScriptObject)self).lookup(desc, request);
} else if (self instanceof Undefined) {
inv = Undefined.lookup(desc);
} else {
- throw new AssertionError(); // Should never reach here.
+ throw new AssertionError(self.getClass().getName()); // Should never reach here.
}
- return Bootstrap.asType(inv, linkerServices, desc);
+ return inv;
}
@Override
@@ -184,7 +188,7 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
*/
private static GuardedInvocation getArrayConverter(final Class<?> sourceType, final Class<?> targetType) {
final boolean isSourceTypeNativeArray = sourceType == NativeArray.class;
- // If source type is more generic than ScriptFunction class, we'll need to use a guard
+ // If source type is more generic than NativeArray class, we'll need to use a guard
final boolean isSourceTypeGeneric = !isSourceTypeNativeArray && sourceType.isAssignableFrom(NativeArray.class);
if (isSourceTypeNativeArray || isSourceTypeGeneric) {
@@ -208,12 +212,12 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
return MH.asType(converter, converter.type().changeReturnType(type));
}
- private static GuardedInvocation getMirrorConverter(Class<?> sourceType, Class<?> targetType) {
+ private static GuardedInvocation getMirrorConverter(final Class<?> sourceType, final Class<?> targetType) {
// Could've also used (targetType.isAssignableFrom(ScriptObjectMirror.class) && targetType != Object.class) but
// it's probably better to explicitly spell out the supported target types
if (targetType == Map.class || targetType == Bindings.class || targetType == JSObject.class || targetType == ScriptObjectMirror.class) {
if(ScriptObject.class.isAssignableFrom(sourceType)) {
- return new GuardedInvocation(CREATE_MIRROR, null);
+ return new GuardedInvocation(CREATE_MIRROR);
}
return new GuardedInvocation(CREATE_MIRROR, IS_SCRIPT_OBJECT);
}
@@ -270,7 +274,7 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
return Comparison.INDETERMINATE;
}
- private static boolean isList(Class<?> clazz) {
+ private static boolean isList(final Class<?> clazz) {
return clazz == List.class || clazz == Deque.class;
}
@@ -288,7 +292,7 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp
@SuppressWarnings("unused")
private static Object createMirror(final Object obj) {
- return ScriptUtils.wrap(obj);
+ return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj;
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
index 22135bc1..e8b8c43a 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
@@ -39,7 +39,7 @@ import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ConsString;
-import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
* Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other
@@ -47,6 +47,9 @@ import jdk.nashorn.internal.runtime.Context;
* primitive type conversions for these types when linking to Java methods.
*/
final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
+ private static final GuardedTypeConversion VOID_TO_OBJECT = new GuardedTypeConversion(
+ new GuardedInvocation(MethodHandles.constant(Object.class, ScriptRuntime.UNDEFINED)), true);
+
@Override
public boolean canLinkType(final Class<?> type) {
return canLinkTypeStatic(type);
@@ -62,10 +65,9 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
final LinkRequest request = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
final Object self = request.getReceiver();
- final Global global = Context.getGlobal();
final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor();
- return Bootstrap.asType(global.primitiveLookup(request, self), linkerServices, desc);
+ return Bootstrap.asTypeSafeReturn(Global.primitiveLookup(request, self), linkerServices, desc);
}
/**
@@ -79,6 +81,9 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) {
final MethodHandle mh = JavaArgumentConverters.getConverter(targetType);
if (mh == null) {
+ if(targetType == Object.class && sourceType == void.class) {
+ return VOID_TO_OBJECT;
+ }
return null;
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
index f8ea9916..c870f39d 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@@ -54,12 +54,12 @@ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker {
private static final GuardingDynamicLinker staticClassLinker = BeansLinker.getLinkerForClass(StaticClass.class);
@Override
- public boolean canLinkType(Class<?> type) {
+ public boolean canLinkType(final Class<?> type) {
return type == StaticClass.class;
}
@Override
- public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception {
+ public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
final LinkRequest request = linkRequest.withoutRuntimeContext(); // Nashorn has no runtime context
final Object self = request.getReceiver();
if (self.getClass() != StaticClass.class) {
@@ -99,7 +99,7 @@ final class NashornStaticClassLinker implements TypeBasedGuardingDynamicLinker {
return delegate(linkerServices, request);
}
- private static GuardedInvocation delegate(LinkerServices linkerServices, final LinkRequest request) throws Exception {
+ private static GuardedInvocation delegate(final LinkerServices linkerServices, final LinkRequest request) throws Exception {
return NashornBeansLinker.getGuardedInvocation(staticClassLinker, request, linkerServices);
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
index 7665be7f..2a536bbf 100644
--- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
+++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@@ -26,17 +26,18 @@
package jdk.nashorn.internal.runtime.linker;
import static jdk.nashorn.internal.lookup.Lookup.MH;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
-import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.FindProperty;
+import jdk.nashorn.internal.runtime.GlobalConstants;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UserAccessorProperty;
/**
* Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and
@@ -59,6 +60,7 @@ public final class PrimitiveLookup {
* creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the
* method - it will be combined into the returned invocation as an argument filter on the receiver.
* @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive
+ * @param protoFilter A method handle that walks up the proto chain of this receiver object
* type {@code receiverClass}.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass,
@@ -77,6 +79,7 @@ public final class PrimitiveLookup {
* @param wrapFilter A method handle that takes a primitive value of type guarded by the {@code guard} and
* creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the
* method - it will be combined into the returned invocation as an argument filter on the receiver.
+ * @param protoFilter A method handle that walks up the proto chain of this receiver object
* @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive
* type (that is implied by both {@code guard} and {@code wrappedReceiver}).
*/
@@ -84,37 +87,42 @@ public final class PrimitiveLookup {
final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
final MethodHandle protoFilter) {
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
- final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
- if ("setProp".equals(operator) || "setElem".equals(operator)) {
- MethodType type = desc.getMethodType();
- MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1)));
- if (type.parameterCount() == 3) {
- method = MH.dropArguments(method, 2, type.parameterType(2));
- }
- return new GuardedInvocation(method, guard);
- }
- if(desc.getNameTokenCount() > 2) {
+ //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem)
+ //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be.
+ //so in that case we can skip creation of primitive wrapper and start our search with the prototype.
+ if (desc.getNameTokenCount() > 2) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final FindProperty find = wrappedReceiver.findProperty(name, true);
- if(find == null) {
+
+ if (find == null) {
// Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
return null;
- } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) {
+ }
+
+ final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter
+ if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) {
+ return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null);
+ }
+
+ if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
// If property is found in the prototype object bind the method handle directly to
// the proto filter instead of going through wrapper instantiation below.
final ScriptObject proto = wrappedReceiver.getProto();
final GuardedInvocation link = proto.lookup(desc, request);
if (link != null) {
- final MethodHandle invocation = link.getInvocation();
+ final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint
+
final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class));
final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter);
final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter);
+
return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard));
}
}
}
+
final GuardedInvocation link = wrappedReceiver.lookup(desc, request);
if (link != null) {
MethodHandle method = link.getInvocation();
@@ -124,8 +132,10 @@ public final class PrimitiveLookup {
assert receiverType.isAssignableFrom(wrapType.returnType());
method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType)));
}
- return new GuardedInvocation(method, guard, link.getSwitchPoint());
+
+ return new GuardedInvocation(method, guard, link.getSwitchPoints(), null);
}
+
return null;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
index 66720c23..10ab4349 100644
--- a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.runtime.linker;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import jdk.internal.dynalink.CallSiteDescriptor;
@@ -33,7 +35,9 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.objects.Global;
/**
* Check java reflection permission for java reflective and java.lang.invoke access from scripts
@@ -100,6 +104,12 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
}
static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
+ final Global global = Context.getGlobal();
+ final ClassFilter cf = global.getClassFilter();
+ if (cf != null && isReflectiveCheckNeeded(clazz, isStatic)) {
+ throw typeError("no.reflection.with.classfilter");
+ }
+
final SecurityManager sm = System.getSecurityManager();
if (sm != null && isReflectiveCheckNeeded(clazz, isStatic)) {
checkReflectionPermission(sm);
@@ -107,6 +117,12 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
}
private static void checkLinkRequest(final LinkRequest origRequest) {
+ final Global global = Context.getGlobal();
+ final ClassFilter cf = global.getClassFilter();
+ if (cf != null) {
+ throw typeError("no.reflection.with.classfilter");
+ }
+
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
diff --git a/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java b/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
new file mode 100644
index 00000000..084f7658
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.logging;
+
+import java.io.PrintWriter;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
+
+/**
+ * Wrapper class for Logging system. This is how you are supposed to register a logger and use it
+ */
+
+public final class DebugLogger {
+
+ /** Disabled logger used for all loggers that need an instance, but shouldn't output anything */
+ public static final DebugLogger DISABLED_LOGGER = new DebugLogger("disabled", Level.OFF, false);
+
+ private final Logger logger;
+ private final boolean isEnabled;
+
+ private int indent;
+
+ private static final int INDENT_SPACE = 4;
+
+ /** A quiet logger only logs {@link RuntimeEvent}s and does't output any text, regardless of level */
+ private final boolean isQuiet;
+
+ /**
+ * Constructor
+ *
+ * A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log}
+ *
+ * @param loggerName name of logger - this is the unique key with which it can be identified
+ * @param loggerLevel level of the logger
+ * @param isQuiet is this a quiet logger, i.e. enabled for things like e.g. RuntimeEvent:s, but quiet otherwise
+ */
+ public DebugLogger(final String loggerName, final Level loggerLevel, final boolean isQuiet) {
+ this.logger = instantiateLogger(loggerName, loggerLevel);
+ this.isQuiet = isQuiet;
+ assert logger != null;
+ this.isEnabled = getLevel() != Level.OFF;
+ }
+
+ private static Logger instantiateLogger(final String name, final Level level) {
+ final Logger logger = java.util.logging.Logger.getLogger(name);
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ for (final Handler h : logger.getHandlers()) {
+ logger.removeHandler(h);
+ }
+
+ logger.setLevel(level);
+ logger.setUseParentHandlers(false);
+ final Handler c = new ConsoleHandler();
+
+ c.setFormatter(new Formatter() {
+ @Override
+ public String format(final LogRecord record) {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append('[')
+ .append(record.getLoggerName())
+ .append("] ")
+ .append(record.getMessage())
+ .append('\n');
+
+ return sb.toString();
+ }
+ });
+ logger.addHandler(c);
+ c.setLevel(level);
+ return null;
+ }
+ }, createLoggerControlAccCtxt());
+
+ return logger;
+ }
+
+ /**
+ * Do not currently support chaining this with parent logger. Logger level null
+ * means disabled
+ * @return level
+ */
+ public Level getLevel() {
+ return logger.getLevel() == null ? Level.OFF : logger.getLevel();
+ }
+
+ /**
+ * Get the output writer for the logger. Loggers always default to
+ * stderr for output as they are used mainly to output debug info
+ *
+ * Can be inherited so this should not be static.
+ *
+ * @return print writer for log output.
+ */
+ @SuppressWarnings("static-method")
+ public PrintWriter getOutputStream() {
+ return Context.getCurrentErr();
+ }
+
+ /**
+ * Add quotes around a string
+ * @param str string
+ * @return quoted string
+ */
+ public static String quote(final String str) {
+ if (str.isEmpty()) {
+ return "''";
+ }
+
+ char startQuote = '\0';
+ char endQuote = '\0';
+ char quote = '\0';
+
+ if (str.startsWith("\\") || str.startsWith("\"")) {
+ startQuote = str.charAt(0);
+ }
+ if (str.endsWith("\\") || str.endsWith("\"")) {
+ endQuote = str.charAt(str.length() - 1);
+ }
+
+ if (startQuote == '\0' || endQuote == '\0') {
+ quote = startQuote == '\0' ? endQuote : startQuote;
+ }
+ if (quote == '\0') {
+ quote = '\'';
+ }
+
+ return (startQuote == '\0' ? quote : startQuote) + str + (endQuote == '\0' ? quote : endQuote);
+ }
+
+ /**
+ * Check if the logger is enabled
+ * @return true if enabled
+ */
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ /**
+ * Check if the logger is enabled
+ * @param logger logger to check, null will return false
+ * @return true if enabled
+ */
+ public static boolean isEnabled(final DebugLogger logger) {
+ return logger != null && logger.isEnabled();
+ }
+
+ /**
+ * If you want to change the indent level of your logger, call indent with a new position.
+ * Positions start at 0 and are increased by one for a new "tab"
+ *
+ * @param pos indent position
+ */
+ public void indent(final int pos) {
+ if (isEnabled) {
+ indent += pos * INDENT_SPACE;
+ }
+ }
+
+ /**
+ * Add an indent position
+ */
+ public void indent() {
+ indent += INDENT_SPACE;
+ }
+
+ /**
+ * Unindent a position
+ */
+ public void unindent() {
+ indent -= INDENT_SPACE;
+ if (indent < 0) {
+ indent = 0;
+ }
+ }
+
+ private static void logEvent(final RuntimeEvent<?> event) {
+ if (event != null) {
+ final Global global = Context.getGlobal();
+ if (global.has("Debug")) {
+ final ScriptObject debug = (ScriptObject)global.get("Debug");
+ final ScriptFunction addRuntimeEvent = (ScriptFunction)debug.get("addRuntimeEvent");
+ ScriptRuntime.apply(addRuntimeEvent, debug, event);
+ }
+ }
+ }
+
+ /**
+ * Check if the logger is above the level of detail given
+ * @see java.util.logging.Level
+ *
+ * The higher the level, the more severe the warning
+ *
+ * @param level logging level
+ * @return true if level is above the given one
+ */
+ public boolean levelCoarserThan(final Level level) {
+ return getLevel().intValue() > level.intValue();
+ }
+
+ /**
+ * Check if the logger is above or equal to the level
+ * of detail given
+ * @see java.util.logging.Level
+ *
+ * The higher the level, the more severe the warning
+ *
+ * @param level logging level
+ * @return true if level is above the given one
+ */
+ public boolean levelCoarserThanOrEqual(final Level level) {
+ return getLevel().intValue() >= level.intValue();
+ }
+
+ /**
+ * Check if the logger is below the level of detail given
+ * @see java.util.logging.Level
+ *
+ * The higher the level, the more severe the warning
+ *
+ * @param level logging level
+ * @return true if level is above the given one
+ */
+ public boolean levelFinerThan(final Level level) {
+ return getLevel().intValue() < level.intValue();
+ }
+
+ /**
+ * Check if the logger is below or equal to the level
+ * of detail given
+ * @see java.util.logging.Level
+ *
+ * The higher the level, the more severe the warning
+ *
+ * @param level logging level
+ * @return true if level is above the given one
+ */
+ public boolean levelFinerThanOrEqual(final Level level) {
+ return getLevel().intValue() <= level.intValue();
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
+ * @param str the string to log
+ */
+ public void finest(final String str) {
+ log(Level.FINEST, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void finest(final RuntimeEvent<?> event, final String str) {
+ finest(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINEST} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void finest(final Object... objs) {
+ log(Level.FINEST, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINEST} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void finest(final RuntimeEvent<?> event, final Object... objs) {
+ finest(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINER} on this logger
+ * @param str the string to log
+ */
+ public void finer(final String str) {
+ log(Level.FINER, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINER} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void finer(final RuntimeEvent<?> event, final String str) {
+ finer(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINER} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void finer(final Object... objs) {
+ log(Level.FINER, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINER} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void finer(final RuntimeEvent<?> event, final Object... objs) {
+ finer(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param str the string to log
+ */
+ public void fine(final String str) {
+ log(Level.FINE, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void fine(final RuntimeEvent<?> event, final String str) {
+ fine(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void fine(final Object... objs) {
+ log(Level.FINE, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void fine(final RuntimeEvent<?> event, final Object... objs) {
+ fine(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#CONFIG} on this logger
+ * @param str the string to log
+ */
+ public void config(final String str) {
+ log(Level.CONFIG, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#CONFIG} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void config(final RuntimeEvent<?> event, final String str) {
+ config(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#CONFIG} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void config(final Object... objs) {
+ log(Level.CONFIG, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#CONFIG} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void config(final RuntimeEvent<?> event, final Object... objs) {
+ config(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#INFO} on this logger
+ * @param str the string to log
+ */
+ public void info(final String str) {
+ log(Level.INFO, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#INFO} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void info(final RuntimeEvent<?> event, final String str) {
+ info(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void info(final Object... objs) {
+ log(Level.INFO, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void info(final RuntimeEvent<?> event, final Object... objs) {
+ info(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#WARNING} on this logger
+ * @param str the string to log
+ */
+ public void warning(final String str) {
+ log(Level.WARNING, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#WARNING} on this logger
+ * @param event optional runtime event to log
+ * @param str the string to log
+ */
+ public void warning(final RuntimeEvent<?> event, final String str) {
+ warning(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void warning(final Object... objs) {
+ log(Level.WARNING, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ * @param event optional runtime event to log
+ */
+ public void warning(final RuntimeEvent<?> event, final Object... objs) {
+ warning(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#SEVERE} on this logger
+ * @param str the string to log
+ */
+ public void severe(final String str) {
+ log(Level.SEVERE, str);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#SEVERE} on this logger
+ * @param str the string to log
+ * @param event optional runtime event to log
+ */
+ public void severe(final RuntimeEvent<?> event, final String str) {
+ severe(str);
+ logEvent(event);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#SEVERE} on this logger
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void severe(final Object... objs) {
+ log(Level.SEVERE, objs);
+ }
+
+ /**
+ * Shorthand for outputting a log string as log level
+ * {@link java.util.logging.Level#FINE} on this logger
+ * @param event optional runtime event to log
+ * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+ */
+ public void severe(final RuntimeEvent<?> event, final Object... objs) {
+ severe(objs);
+ logEvent(event);
+ }
+
+ /**
+ * Output log line on this logger at a given level of verbosity
+ * @see java.util.logging.Level
+ *
+ * @param level minimum log level required for logging to take place
+ * @param str string to log
+ */
+ public void log(final Level level, final String str) {
+ if (isEnabled && !isQuiet) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0 ; i < indent ; i++) {
+ sb.append(' ');
+ }
+ sb.append(str);
+ logger.log(level, sb.toString());
+ }
+ }
+
+ /**
+ * Output log line on this logger at a given level of verbosity
+ * @see java.util.logging.Level
+ *
+ * @param level minimum log level required for logging to take place
+ * @param objs objects for which to invoke toString and concatenate to log
+ */
+ public void log(final Level level, final Object... objs) {
+ if (isEnabled && !isQuiet) {
+ final StringBuilder sb = new StringBuilder();
+ for (final Object obj : objs) {
+ sb.append(obj);
+ }
+ log(level, sb.toString());
+ }
+ }
+
+ /**
+ * Access control context for logger level and instantiation permissions
+ * @return access control context
+ */
+ private static AccessControlContext createLoggerControlAccCtxt() {
+ final Permissions perms = new Permissions();
+ perms.add(new LoggingPermission("control", null));
+ return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
+ }
+
+}
diff --git a/src/jdk/nashorn/internal/runtime/logging/Loggable.java b/src/jdk/nashorn/internal/runtime/logging/Loggable.java
new file mode 100644
index 00000000..32950035
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/logging/Loggable.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.logging;
+
+import jdk.nashorn.internal.runtime.Context;
+
+/**
+ * Interface implemented by classes that are loggable.
+ * Their instances will provide functionality for initializing
+ * a logger (usually by asking Global for it, with a reference
+ * to this.getClass()) and a method to return the logger in
+ * use
+ *
+ * Typically a class implementing this interface also has the
+ * Logger annotation
+ *
+ * @see Logger
+ */
+public interface Loggable {
+ /**
+ * Initialize a logger, by asking Context to get or create it
+ * and then keep it in a table by name
+ *
+ * @param context context
+ * @return the initialized logger
+ */
+ public DebugLogger initLogger(final Context context);
+
+ /**
+ * Return the logger in use
+ * @return logger
+ */
+ public DebugLogger getLogger();
+}
diff --git a/src/jdk/nashorn/internal/runtime/logging/Logger.java b/src/jdk/nashorn/internal/runtime/logging/Logger.java
new file mode 100644
index 00000000..a407fec3
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/logging/Logger.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.logging;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation is associated with a class that has a logger.
+ * It contains a name property of the logger name. e.g. a class
+ * whose logger can be initialized by --log:fields, should be
+ * annotated @Logger(name="fields"). Multiple classes can have
+ * the same annotation, which will make them use the same logger
+ * object. Usually a class with this annotation is also a Loggable,
+ * but it is not a hard demand
+ *
+ * @see Loggable
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Logger {
+ /**
+ * Get the name of the logger
+ * @return logger name
+ */
+ public String name() default "";
+}
diff --git a/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java b/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
index bbf1620a..aee6caf0 100644
--- a/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
+++ b/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
@@ -36,7 +36,7 @@ import java.util.StringTokenizer;
*
* {@code --log=module1:level1,module2:level2... }
*/
-public final class KeyValueOption extends Option<String> {
+public class KeyValueOption extends Option<String> {
/**
* Map of keys given
*/
diff --git a/src/jdk/nashorn/internal/runtime/options/LoggingOption.java b/src/jdk/nashorn/internal/runtime/options/LoggingOption.java
new file mode 100644
index 00000000..e1d9cede
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/options/LoggingOption.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.options;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+
+/**
+ * Class that collects logging options like --log=compiler:finest,fields,recompile:fine into
+ * a map form that can be used to instantiate loggers in the Global object on demand
+ */
+public class LoggingOption extends KeyValueOption {
+
+ /**
+ * Logging info. Basically a logger name maps to this,
+ * which is a tuple of log level and the "is quiet" flag,
+ * which is a special log level used to collect RuntimeEvents
+ * only, but not output anything
+ */
+ public static class LoggerInfo {
+ private final Level level;
+ private final boolean isQuiet;
+
+ LoggerInfo(final Level level, final boolean isQuiet) {
+ this.level = level;
+ this.isQuiet = isQuiet;
+ }
+
+ /**
+ * Get the log level
+ * @return log level
+ */
+ public Level getLevel() {
+ return level;
+ }
+
+ /**
+ * Get the quiet flag
+ * @return true if quiet flag is set
+ */
+ public boolean isQuiet() {
+ return isQuiet;
+ }
+ }
+
+ private final Map<String, LoggerInfo> loggers = new HashMap<>();
+
+ LoggingOption(final String value) {
+ super(value);
+ initialize(getValues());
+ }
+
+ /**
+ * Return the logger info collected from this command line option
+ *
+ * @return map of logger name to logger info
+ */
+ public Map<String, LoggerInfo> getLoggers() {
+ return Collections.unmodifiableMap(loggers);
+ }
+
+ /**
+ * Initialization function that is called to instantiate the logging system. It takes
+ * logger names (keys) and logging labels respectively
+ *
+ * @param map a map where the key is a logger name and the value a logging level
+ * @throws IllegalArgumentException if level or names cannot be parsed
+ */
+ private void initialize(final Map<String, String> logMap) throws IllegalArgumentException {
+ try {
+ for (final Entry<String, String> entry : logMap.entrySet()) {
+ Level level;
+ final String name = lastPart(entry.getKey());
+ final String levelString = entry.getValue().toUpperCase(Locale.ENGLISH);
+ final boolean isQuiet;
+
+ if ("".equals(levelString)) {
+ level = Level.INFO;
+ isQuiet = false;
+ } else if ("QUIET".equals(levelString)) {
+ level = Level.INFO;
+ isQuiet = true;
+ } else {
+ level = Level.parse(levelString);
+ isQuiet = false;
+ }
+
+ loggers.put(name, new LoggerInfo(level, isQuiet));
+ }
+ } catch (final IllegalArgumentException | SecurityException e) {
+ throw e;
+ }
+ }
+
+
+
+ private static String lastPart(final String packageName) {
+ final String[] parts = packageName.split("\\.");
+ if (parts.length == 0) {
+ return packageName;
+ }
+ return parts[parts.length - 1];
+ }
+
+
+}
diff --git a/src/jdk/nashorn/internal/runtime/options/Options.java b/src/jdk/nashorn/internal/runtime/options/Options.java
index cd774bb3..ed39fa95 100644
--- a/src/jdk/nashorn/internal/runtime/options/Options.java
+++ b/src/jdk/nashorn/internal/runtime/options/Options.java
@@ -48,7 +48,6 @@ import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
-import jdk.nashorn.internal.runtime.Logging;
import jdk.nashorn.internal.runtime.QuotedStringTokenizer;
/**
@@ -79,7 +78,10 @@ public final class Options {
/** The options map of enabled options */
private final TreeMap<String, Option<?>> options;
- /** System property that can be used for command line option propagation */
+ /** System property that can be used to prepend options to the explicitly specified command line. */
+ private static final String NASHORN_ARGS_PREPEND_PROPERTY = "nashorn.args.prepend";
+
+ /** System property that can be used to append options to the explicitly specified command line. */
private static final String NASHORN_ARGS_PROPERTY = "nashorn.args";
/**
@@ -137,9 +139,10 @@ public final class Options {
* Convenience function for getting system properties in a safe way
* @param name of boolean property
- * @return true if set to true, false if unset or set to false
+ * @param defValue default value of boolean property
+ * @return true if set to true, default value if unset or set to false
*/
- public static boolean getBooleanProperty(final String name) {
+ public static boolean getBooleanProperty(final String name, final Boolean defValue) {
name.getClass(); // null check
if (!name.startsWith("nashorn.")) {
throw new IllegalArgumentException(name);
@@ -151,6 +154,9 @@ public final class Options {
public Boolean run() {
try {
final String property = System.getProperty(name);
+ if (property == null && defValue != null) {
+ return defValue;
+ }
return property != null && !"false".equalsIgnoreCase(property);
} catch (final SecurityException e) {
// if no permission to read, assume false
@@ -162,6 +168,16 @@ public final class Options {
/**
* Convenience function for getting system properties in a safe way
+
+ * @param name of boolean property
+ * @return true if set to true, false if unset or set to false
+ */
+ public static boolean getBooleanProperty(final String name) {
+ return getBooleanProperty(name, null);
+ }
+
+ /**
+ * Convenience function for getting system properties in a safe way
*
* @param name of string property
* @param defValue the default value if unset
@@ -406,15 +422,9 @@ public final class Options {
*/
public void process(final String[] args) {
final LinkedList<String> argList = new LinkedList<>();
+ addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList);
Collections.addAll(argList, args);
-
- final String extra = getStringProperty(NASHORN_ARGS_PROPERTY, null);
- if (extra != null) {
- final StringTokenizer st = new StringTokenizer(extra);
- while (st.hasMoreTokens()) {
- argList.add(st.nextToken());
- }
- }
+ addSystemProperties(NASHORN_ARGS_PROPERTY, argList);
while (!argList.isEmpty()) {
final String arg = argList.remove(0);
@@ -496,6 +506,16 @@ public final class Options {
}
}
+ private static void addSystemProperties(final String sysPropName, final List<String> argList) {
+ final String sysArgs = getStringProperty(sysPropName, null);
+ if (sysArgs != null) {
+ final StringTokenizer st = new StringTokenizer(sysArgs);
+ while (st.hasMoreTokens()) {
+ argList.add(st.nextToken());
+ }
+ }
+ }
+
private static OptionTemplate getOptionTemplate(final String key) {
for (final OptionTemplate t : Options.validOptions) {
if (t.matches(key)) {
@@ -518,14 +538,12 @@ public final class Options {
case "keyvalues":
return new KeyValueOption(value);
case "log":
- final KeyValueOption kv = new KeyValueOption(value);
- Logging.initialize(kv.getValues());
- return kv;
+ return new LoggingOption(value);
case "boolean":
return new Option<>(value != null && Boolean.parseBoolean(value));
case "integer":
try {
- return new Option<>((value == null) ? 0 : Integer.parseInt(value));
+ return new Option<>(value == null ? 0 : Integer.parseInt(value));
} catch (final NumberFormatException nfe) {
throw new IllegalOptionException(t);
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
index f5158021..525a2a51 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
@@ -25,8 +25,6 @@
package jdk.nashorn.internal.runtime.regexp;
-import jdk.nashorn.internal.runtime.ParserException;
-
import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static java.util.regex.Pattern.MULTILINE;
import static java.util.regex.Pattern.UNICODE_CASE;
@@ -34,6 +32,7 @@ import static java.util.regex.Pattern.UNICODE_CASE;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import jdk.nashorn.internal.runtime.ParserException;
/**
* Default regular expression implementation based on java.util.regex package.
diff --git a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
index 47dbd7c4..a6023389 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.runtime.regexp;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.regexp.joni.Matcher;
import jdk.nashorn.internal.runtime.regexp.joni.Option;
@@ -33,9 +35,6 @@ import jdk.nashorn.internal.runtime.regexp.joni.Region;
import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
/**
* Regular expression implementation based on the Joni engine from the JRuby project.
*/
@@ -77,7 +76,7 @@ public class JoniRegExp extends RegExp {
}
if (parsed != null) {
- char[] javaPattern = parsed.getJavaPattern().toCharArray();
+ final char[] javaPattern = parsed.getJavaPattern().toCharArray();
this.regex = new Regex(javaPattern, 0, javaPattern.length, option, Syntax.JAVASCRIPT);
this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/RegExp.java b/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
index 65c944e1..ac57c9fb 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
@@ -25,12 +25,11 @@
package jdk.nashorn.internal.runtime.regexp;
+import java.util.regex.MatchResult;
import jdk.nashorn.internal.runtime.BitVector;
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ParserException;
-import java.util.regex.MatchResult;
-
/**
* This is the base class for representing a parsed regular expression.
*
diff --git a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
index 08168b63..77b1b3dc 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.runtime.regexp;
+import java.util.Collections;
+import java.util.Set;
+import java.util.WeakHashMap;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.options.Options;
@@ -39,6 +42,15 @@ public class RegExpFactory {
private final static String JDK = "jdk";
private final static String JONI = "joni";
+ /** Weak cache of already validated regexps - when reparsing, we don't, for example
+ * need to recompile (reverify) all regexps that have previously been parsed by this
+ * RegExpFactory in a previous compilation. This saves significant time in e.g. avatar
+ * startup */
+ private static final Set<String> VALID_CACHE_SET =
+ Collections.newSetFromMap(
+ Collections.synchronizedMap(
+ new WeakHashMap<String, Boolean>()));
+
static {
final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
switch (impl) {
@@ -88,7 +100,9 @@ public class RegExpFactory {
*/
// @SuppressWarnings({"unused"})
public static void validate(final String pattern, final String flags) throws ParserException {
- instance.compile(pattern, flags);
+ if (VALID_CACHE_SET.add(pattern + flags)) {
+ instance.compile(pattern, flags);
+ }
}
/**
diff --git a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
index f4edecc4..88b023ac 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
@@ -31,7 +31,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.PatternSyntaxException;
-
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.parser.Scanner;
import jdk.nashorn.internal.runtime.BitVector;
@@ -101,7 +100,7 @@ final class RegExpScanner extends Scanner {
private void processForwardReferences() {
- Iterator<Integer> iterator = forwardReferences.descendingIterator();
+ final Iterator<Integer> iterator = forwardReferences.descendingIterator();
while (iterator.hasNext()) {
final int pos = iterator.next();
final int num = iterator.next();
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
index eb612cd3..64d90c03 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
@@ -27,9 +27,7 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
import static jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode.newAltNode;
import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
-
import java.util.HashSet;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
@@ -50,10 +48,11 @@ import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;
final class Analyser extends Parser {
- protected Analyser(ScanEnvironment env, char[] chars, int p, int end) {
+ protected Analyser(final ScanEnvironment env, final char[] chars, final int p, final int end) {
super(env, chars, p, end);
}
+ @SuppressWarnings("unused")
protected final void compile() {
if (Config.DEBUG) {
Config.log.println(new String(chars, getBegin(), getEnd()));
@@ -77,7 +76,9 @@ final class Analyser extends Parser {
root = setupTree(root, 0);
if (Config.DEBUG_PARSE_TREE) {
- if (Config.DEBUG_PARSE_TREE_RAW) Config.log.println("<TREE>");
+ if (Config.DEBUG_PARSE_TREE_RAW) {
+ Config.log.println("<TREE>");
+ }
root.verifyTree(new HashSet<Node>(), env.reg.warnings);
Config.log.println(root + "\n");
}
@@ -95,7 +96,9 @@ final class Analyser extends Parser {
regex.clearOptimizeInfo();
- if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);
+ if (!Config.DONT_OPTIMIZE) {
+ setOptimizedInfoFromTree(root);
+ }
env.memNodes = null;
@@ -111,13 +114,15 @@ final class Analyser extends Parser {
if (Config.DEBUG_COMPILE) {
Config.log.println("stack used: " + regex.stackNeeded);
- if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
+ if (Config.USE_STRING_TEMPLATES) {
+ Config.log.print("templates: " + regex.templateNum + "\n");
+ }
Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
} // DEBUG_COMPILE
}
- private void swap(Node a, Node b) {
+ private void swap(final Node a, final Node b) {
a.swap(b);
if (root == b) {
@@ -128,7 +133,7 @@ final class Analyser extends Parser {
}
// USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
- private int quantifiersMemoryInfo(Node node) {
+ private int quantifiersMemoryInfo(final Node node) {
int info = 0;
switch(node.getType()) {
@@ -136,20 +141,22 @@ final class Analyser extends Parser {
case NodeType.ALT:
ConsAltNode can = (ConsAltNode)node;
do {
- int v = quantifiersMemoryInfo(can.car);
- if (v > info) info = v;
+ final int v = quantifiersMemoryInfo(can.car);
+ if (v > info) {
+ info = v;
+ }
} while ((can = can.cdr) != null);
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.upper != 0) {
info = quantifiersMemoryInfo(qn.target);
}
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.MEMORY:
return TargetInfo.IS_EMPTY_MEM;
@@ -177,13 +184,15 @@ final class Analyser extends Parser {
return info;
}
- private int getMinMatchLength(Node node) {
+ private int getMinMatchLength(final Node node) {
int min = 0;
switch (node.getType()) {
case NodeType.BREF:
- BackRefNode br = (BackRefNode)node;
- if (br.isRecursion()) break;
+ final BackRefNode br = (BackRefNode)node;
+ if (br.isRecursion()) {
+ break;
+ }
if (br.backRef > env.numMem) {
throw new ValueException(ERR_INVALID_BACKREF);
@@ -202,8 +211,8 @@ final class Analyser extends Parser {
case NodeType.ALT:
ConsAltNode y = (ConsAltNode)node;
do {
- Node x = y.car;
- int tmin = getMinMatchLength(x);
+ final Node x = y.car;
+ final int tmin = getMinMatchLength(x);
if (y == node) {
min = tmin;
} else if (min > tmin) {
@@ -226,7 +235,7 @@ final class Analyser extends Parser {
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.lower > 0) {
min = getMinMatchLength(qn.target);
min = MinMaxLen.distanceMultiply(min, qn.lower);
@@ -234,7 +243,7 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.MEMORY:
if (en.isMinFixed()) {
@@ -250,6 +259,9 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
min = getMinMatchLength(en.target);
break;
+
+ default:
+ break;
} // inner switch
break;
@@ -261,14 +273,14 @@ final class Analyser extends Parser {
return min;
}
- private int getMaxMatchLength(Node node) {
+ private int getMaxMatchLength(final Node node) {
int max = 0;
switch (node.getType()) {
case NodeType.LIST:
ConsAltNode ln = (ConsAltNode)node;
do {
- int tmax = getMaxMatchLength(ln.car);
+ final int tmax = getMaxMatchLength(ln.car);
max = MinMaxLen.distanceAdd(max, tmax);
} while ((ln = ln.cdr) != null);
break;
@@ -276,8 +288,10 @@ final class Analyser extends Parser {
case NodeType.ALT:
ConsAltNode an = (ConsAltNode)node;
do {
- int tmax = getMaxMatchLength(an.car);
- if (max < tmax) max = tmax;
+ final int tmax = getMaxMatchLength(an.car);
+ if (max < tmax) {
+ max = tmax;
+ }
} while ((an = an.cdr) != null);
break;
@@ -295,7 +309,7 @@ final class Analyser extends Parser {
break;
case NodeType.BREF:
- BackRefNode br = (BackRefNode)node;
+ final BackRefNode br = (BackRefNode)node;
if (br.isRecursion()) {
max = MinMaxLen.INFINITE_DISTANCE;
break;
@@ -304,12 +318,14 @@ final class Analyser extends Parser {
if (br.backRef > env.numMem) {
throw new ValueException(ERR_INVALID_BACKREF);
}
- int tmax = getMaxMatchLength(env.memNodes[br.backRef]);
- if (max < tmax) max = tmax;
+ final int tmax = getMaxMatchLength(env.memNodes[br.backRef]);
+ if (max < tmax) {
+ max = tmax;
+ }
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.upper != 0) {
max = getMaxMatchLength(qn.target);
if (max != 0) {
@@ -323,7 +339,7 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.MEMORY:
if (en.isMaxFixed()) {
@@ -339,6 +355,9 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
max = getMaxMatchLength(en.target);
break;
+
+ default:
+ break;
} // inner switch
break;
@@ -352,12 +371,12 @@ final class Analyser extends Parser {
private static final int GET_CHAR_LEN_VARLEN = -1;
private static final int GET_CHAR_LEN_TOP_ALT_VARLEN = -2;
- protected final int getCharLengthTree(Node node) {
+ protected final int getCharLengthTree(final Node node) {
return getCharLengthTree(node, 0);
}
- private int getCharLengthTree(Node node, int level) {
- level++;
+ private int getCharLengthTree(final Node node, final int levelp) {
+ final int level = levelp + 1;
int len = 0;
returnCode = 0;
@@ -366,8 +385,10 @@ final class Analyser extends Parser {
case NodeType.LIST:
ConsAltNode ln = (ConsAltNode)node;
do {
- int tlen = getCharLengthTree(ln.car, level);
- if (returnCode == 0) len = MinMaxLen.distanceAdd(len, tlen);
+ final int tlen = getCharLengthTree(ln.car, level);
+ if (returnCode == 0) {
+ len = MinMaxLen.distanceAdd(len, tlen);
+ }
} while (returnCode == 0 && (ln = ln.cdr) != null);
break;
@@ -377,9 +398,11 @@ final class Analyser extends Parser {
int tlen = getCharLengthTree(an.car, level);
while (returnCode == 0 && (an = an.cdr) != null) {
- int tlen2 = getCharLengthTree(an.car, level);
+ final int tlen2 = getCharLengthTree(an.car, level);
if (returnCode == 0) {
- if (tlen != tlen2) varLen = true;
+ if (tlen != tlen2) {
+ varLen = true;
+ }
}
}
@@ -397,15 +420,17 @@ final class Analyser extends Parser {
break;
case NodeType.STR:
- StringNode sn = (StringNode)node;
+ final StringNode sn = (StringNode)node;
len = sn.length();
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.lower == qn.upper) {
tlen = getCharLengthTree(qn.target, level);
- if (returnCode == 0) len = MinMaxLen.distanceMultiply(tlen, qn.lower);
+ if (returnCode == 0) {
+ len = MinMaxLen.distanceMultiply(tlen, qn.lower);
+ }
} else {
returnCode = GET_CHAR_LEN_VARLEN;
}
@@ -418,7 +443,7 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch(en.type) {
case EncloseType.MEMORY:
if (en.isCLenFixed()) {
@@ -436,6 +461,9 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
len = getCharLengthTree(en.target, level);
break;
+
+ default:
+ break;
} // inner switch
break;
@@ -449,13 +477,15 @@ final class Analyser extends Parser {
}
/* x is not included y ==> 1 : 0 */
- private boolean isNotIncluded(Node x, Node y) {
+ private static boolean isNotIncluded(final Node xn, final Node yn) {
+ Node x = xn;
+ Node y = yn;
Node tmp;
// !retry:!
retry: while(true) {
- int yType = y.getType();
+ final int yType = y.getType();
switch(x.getType()) {
case NodeType.CTYPE:
@@ -482,21 +512,25 @@ final class Analyser extends Parser {
break;
case NodeType.CCLASS:
- CClassNode xc = (CClassNode)x;
+ final CClassNode xc = (CClassNode)x;
switch(yType) {
case NodeType.CCLASS:
- CClassNode yc = (CClassNode)y;
+ final CClassNode yc = (CClassNode)y;
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
boolean v = xc.bs.at(i);
if ((v && !xc.isNot()) || (!v && xc.isNot())) {
v = yc.bs.at(i);
- if ((v && !yc.isNot()) || (!v && yc.isNot())) return false;
+ if ((v && !yc.isNot()) || (!v && yc.isNot())) {
+ return false;
+ }
}
}
- if ((xc.mbuf == null && !xc.isNot()) || yc.mbuf == null && !yc.isNot()) return true;
+ if ((xc.mbuf == null && !xc.isNot()) || yc.mbuf == null && !yc.isNot()) {
+ return true;
+ }
return false;
// break; not reached
@@ -514,26 +548,31 @@ final class Analyser extends Parser {
break; // case NodeType.CCLASS
case NodeType.STR:
- StringNode xs = (StringNode)x;
- if (xs.length() == 0) break;
+ final StringNode xs = (StringNode)x;
+ if (xs.length() == 0) {
+ break;
+ }
switch (yType) {
case NodeType.CCLASS:
- CClassNode cc = (CClassNode)y;
- int code = xs.chars[xs.p];
+ final CClassNode cc = (CClassNode)y;
+ final int code = xs.chars[xs.p];
return !cc.isCodeInCC(code);
case NodeType.STR:
- StringNode ys = (StringNode)y;
+ final StringNode ys = (StringNode)y;
int len = xs.length();
- if (len > ys.length()) len = ys.length();
+ if (len > ys.length()) {
+ len = ys.length();
+ }
if (xs.isAmbig() || ys.isAmbig()) {
/* tiny version */
return false;
- } else {
- for (int i=0, p=ys.p, q=xs.p; i<len; i++, p++, q++) {
- if (ys.chars[p] != xs.chars[q]) return true;
+ }
+ for (int i=0, pt=ys.p, q=xs.p; i<len; i++, pt++, q++) {
+ if (ys.chars[pt] != xs.chars[q]) {
+ return true;
}
}
break;
@@ -543,6 +582,8 @@ final class Analyser extends Parser {
} // inner switch
break; // case NodeType.STR
+ default:
+ break;
} // switch
@@ -551,7 +592,7 @@ final class Analyser extends Parser {
return false;
}
- private Node getHeadValueNode(Node node, boolean exact) {
+ private Node getHeadValueNode(final Node node, final boolean exact) {
Node n = null;
switch(node.getType()) {
@@ -562,7 +603,9 @@ final class Analyser extends Parser {
case NodeType.CTYPE:
case NodeType.CCLASS:
- if (!exact) n = node;
+ if (!exact) {
+ n = node;
+ }
break;
case NodeType.LIST:
@@ -570,8 +613,11 @@ final class Analyser extends Parser {
break;
case NodeType.STR:
- StringNode sn = (StringNode)node;
- if (sn.end <= sn.p) break; // ???
+ final StringNode sn = (StringNode)node;
+ if (sn.end <= sn.p)
+ {
+ break; // ???
+ }
if (exact && !sn.isRaw() && isIgnoreCase(regex.options)){
// nothing
@@ -581,7 +627,7 @@ final class Analyser extends Parser {
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.lower > 0) {
if (qn.headExact != null) {
n = qn.headExact;
@@ -592,11 +638,11 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.OPTION:
- int options = regex.options;
+ final int options = regex.options;
regex.options = en.option;
n = getHeadValueNode(en.target, exact);
regex.options = options;
@@ -606,12 +652,17 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
n = getHeadValueNode(en.target, exact);
break;
+
+ default:
+ break;
} // inner switch
break;
case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
- if (an.type == AnchorType.PREC_READ) n = getHeadValueNode(an.target, exact);
+ final AnchorNode an = (AnchorNode)node;
+ if (an.type == AnchorType.PREC_READ) {
+ n = getHeadValueNode(an.target, exact);
+ }
break;
default:
@@ -622,8 +673,10 @@ final class Analyser extends Parser {
}
// true: invalid
- private boolean checkTypeTree(Node node, int typeMask, int encloseMask, int anchorMask) {
- if ((node.getType2Bit() & typeMask) == 0) return true;
+ private boolean checkTypeTree(final Node node, final int typeMask, final int encloseMask, final int anchorMask) {
+ if ((node.getType2Bit() & typeMask) == 0) {
+ return true;
+ }
boolean invalid = false;
@@ -641,16 +694,22 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
- if ((en.type & encloseMask) == 0) return true;
+ final EncloseNode en = (EncloseNode)node;
+ if ((en.type & encloseMask) == 0) {
+ return true;
+ }
invalid = checkTypeTree(en.target, typeMask, encloseMask, anchorMask);
break;
case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
- if ((an.type & anchorMask) == 0) return true;
+ final AnchorNode an = (AnchorNode)node;
+ if ((an.type & anchorMask) == 0) {
+ return true;
+ }
- if (an.target != null) invalid = checkTypeTree(an.target, typeMask, encloseMask, anchorMask);
+ if (an.target != null) {
+ invalid = checkTypeTree(an.target, typeMask, encloseMask, anchorMask);
+ }
break;
default:
@@ -665,15 +724,16 @@ final class Analyser extends Parser {
(?<=A|B) ==> (?<=A)|(?<=B)
(?<!A|B) ==> (?<!A)(?<!B)
*/
- private Node divideLookBehindAlternatives(Node node) {
- AnchorNode an = (AnchorNode)node;
- int anchorType = an.type;
+ private Node divideLookBehindAlternatives(final Node nodep) {
+ Node node = nodep;
+ final AnchorNode an = (AnchorNode)node;
+ final int anchorType = an.type;
Node head = an.target;
Node np = ((ConsAltNode)head).car;
swap(node, head);
- Node tmp = node;
+ final Node tmp = node;
node = head;
head = tmp;
@@ -682,7 +742,7 @@ final class Analyser extends Parser {
np = node;
while ((np = ((ConsAltNode)np).cdr) != null) {
- AnchorNode insert = new AnchorNode(anchorType);
+ final AnchorNode insert = new AnchorNode(anchorType);
insert.setTarget(((ConsAltNode)np).car);
((ConsAltNode)np).setCar(insert);
}
@@ -697,10 +757,10 @@ final class Analyser extends Parser {
return node;
}
- private Node setupLookBehind(Node node) {
- AnchorNode an = (AnchorNode)node;
- int len = getCharLengthTree(an.target);
- switch(returnCode) {
+ private Node setupLookBehind(final Node node) {
+ final AnchorNode an = (AnchorNode)node;
+ final int len = getCharLengthTree(an.target);
+ switch (returnCode) {
case 0:
an.charLength = len;
break;
@@ -709,23 +769,26 @@ final class Analyser extends Parser {
case GET_CHAR_LEN_TOP_ALT_VARLEN:
if (syntax.differentLengthAltLookBehind()) {
return divideLookBehindAlternatives(node);
- } else {
- throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
}
+ throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
+ default:
+ break;
}
return node;
}
- private void nextSetup(Node node, Node nextNode) {
+ private void nextSetup(final Node nodep, final Node nextNode) {
+ Node node = nodep;
+
// retry:
retry: while(true) {
- int type = node.getType();
+ final int type = node.getType();
if (type == NodeType.QTFR) {
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
if (qn.greedy && isRepeatInfinite(qn.upper)) {
if (Config.USE_QTFR_PEEK_NEXT) {
- StringNode n = (StringNode)getHeadValueNode(nextNode, true);
+ final StringNode n = (StringNode)getHeadValueNode(nextNode, true);
/* '\0': for UTF-16BE etc... */
if (n != null && n.chars[n.p] != 0) { // ?????????
qn.nextHeadExact = n;
@@ -734,11 +797,11 @@ final class Analyser extends Parser {
/* automatic posseivation a*b ==> (?>a*)b */
if (qn.lower <= 1) {
if (qn.target.isSimple()) {
- Node x = getHeadValueNode(qn.target, false);
+ final Node x = getHeadValueNode(qn.target, false);
if (x != null) {
- Node y = getHeadValueNode(nextNode, false);
+ final Node y = getHeadValueNode(nextNode, false);
if (y != null && isNotIncluded(x, y)) {
- EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); //onig_node_new_enclose
+ final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); //onig_node_new_enclose
en.setStopBtSimpleRepeat();
//en.setTarget(qn.target); // optimize it ??
swap(node, en);
@@ -750,7 +813,7 @@ final class Analyser extends Parser {
}
}
} else if (type == NodeType.ENCLOSE) {
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
if (en.isMemory()) {
node = en.target;
// !goto retry;!
@@ -762,26 +825,26 @@ final class Analyser extends Parser {
} // while
}
- private void updateStringNodeCaseFoldMultiByte(StringNode sn) {
- char[] chars = sn.chars;
- int end = sn.end;
+ private void updateStringNodeCaseFoldMultiByte(final StringNode sn) {
+ final char[] ch = sn.chars;
+ final int end = sn.end;
value = sn.p;
int sp = 0;
char buf;
while (value < end) {
- int ovalue = value;
- buf = EncodingHelper.toLowerCase(chars[value++]);
+ final int ovalue = value;
+ buf = EncodingHelper.toLowerCase(ch[value++]);
- if (chars[ovalue] != buf) {
+ if (ch[ovalue] != buf) {
char[] sbuf = new char[sn.length() << 1];
- System.arraycopy(chars, sn.p, sbuf, 0, ovalue - sn.p);
+ System.arraycopy(ch, sn.p, sbuf, 0, ovalue - sn.p);
value = ovalue;
while (value < end) {
- buf = EncodingHelper.toLowerCase(chars[value++]);
+ buf = EncodingHelper.toLowerCase(ch[value++]);
if (sp >= sbuf.length) {
- char[]tmp = new char[sbuf.length << 1];
+ final char[]tmp = new char[sbuf.length << 1];
System.arraycopy(sbuf, 0, tmp, 0, sbuf.length);
sbuf = tmp;
}
@@ -794,13 +857,13 @@ final class Analyser extends Parser {
}
}
- private void updateStringNodeCaseFold(Node node) {
- StringNode sn = (StringNode)node;
+ private void updateStringNodeCaseFold(final Node node) {
+ final StringNode sn = (StringNode)node;
updateStringNodeCaseFoldMultiByte(sn);
}
- private Node expandCaseFoldMakeRemString(char[] chars, int p, int end) {
- StringNode node = new StringNode(chars, p, end);
+ private Node expandCaseFoldMakeRemString(final char[] ch, final int pp, final int end) {
+ final StringNode node = new StringNode(ch, pp, end);
updateStringNodeCaseFold(node);
node.setAmbig();
@@ -808,8 +871,8 @@ final class Analyser extends Parser {
return node;
}
- private boolean expandCaseFoldStringAlt(int itemNum, char[] items,
- char[] chars, int p, int slen, int end, ObjPtr<Node> node) {
+ private static boolean expandCaseFoldStringAlt(final int itemNum, final char[] items,
+ final char[] chars, final int p, final int slen, final int end, final ObjPtr<Node> node) {
ConsAltNode altNode;
node.p = altNode = newAltNode(null, null);
@@ -822,7 +885,7 @@ final class Analyser extends Parser {
snode.catCode(items[i]);
- ConsAltNode an = newAltNode(null, null);
+ final ConsAltNode an = newAltNode(null, null);
an.setCar(snode);
altNode.setCdr(an);
altNode = an;
@@ -831,66 +894,75 @@ final class Analyser extends Parser {
}
private static final int THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION = 8;
- private Node expandCaseFoldString(Node node) {
- StringNode sn = (StringNode)node;
+ private Node expandCaseFoldString(final Node node) {
+ final StringNode sn = (StringNode)node;
- if (sn.isAmbig() || sn.length() <= 0) return node;
+ if (sn.isAmbig() || sn.length() <= 0) {
+ return node;
+ }
- char[] chars = sn.chars;
- int p = sn.p;
- int end = sn.end;
+ final char[] chars1 = sn.chars;
+ int pt = sn.p;
+ final int end = sn.end;
int altNum = 1;
- ConsAltNode topRoot = null, root = null;
- ObjPtr<Node> prevNode = new ObjPtr<Node>();
+ ConsAltNode topRoot = null, r = null;
+ @SuppressWarnings("unused")
+ final ObjPtr<Node> prevNode = new ObjPtr<Node>();
StringNode stringNode = null;
- while (p < end) {
- char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars[p]);
+ while (pt < end) {
+ final char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars1[pt]);
if (items.length == 0) {
if (stringNode == null) {
- if (root == null && prevNode.p != null) {
- topRoot = root = ConsAltNode.listAdd(null, prevNode.p);
+ if (r == null && prevNode.p != null) {
+ topRoot = r = ConsAltNode.listAdd(null, prevNode.p);
}
prevNode.p = stringNode = new StringNode(); // onig_node_new_str(NULL, NULL);
- if (root != null) ConsAltNode.listAdd(root, stringNode);
+ if (r != null) {
+ ConsAltNode.listAdd(r, stringNode);
+ }
}
- stringNode.cat(chars, p, p + 1);
+ stringNode.cat(chars1, pt, pt + 1);
} else {
altNum *= (items.length + 1);
- if (altNum > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break;
+ if (altNum > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) {
+ break;
+ }
- if (root == null && prevNode.p != null) {
- topRoot = root = ConsAltNode.listAdd(null, prevNode.p);
+ if (r == null && prevNode.p != null) {
+ topRoot = r = ConsAltNode.listAdd(null, prevNode.p);
}
- expandCaseFoldStringAlt(items.length, items, chars, p, 1, end, prevNode);
- if (root != null) ConsAltNode.listAdd(root, prevNode.p);
+ expandCaseFoldStringAlt(items.length, items, chars1, pt, 1, end, prevNode);
+ if (r != null) {
+ ConsAltNode.listAdd(r, prevNode.p);
+ }
stringNode = null;
}
- p++;
+ pt++;
}
- if (p < end) {
- Node srem = expandCaseFoldMakeRemString(chars, p, end);
+ if (pt < end) {
+ final Node srem = expandCaseFoldMakeRemString(chars1, pt, end);
- if (prevNode.p != null && root == null) {
- topRoot = root = ConsAltNode.listAdd(null, prevNode.p);
+ if (prevNode.p != null && r == null) {
+ topRoot = r = ConsAltNode.listAdd(null, prevNode.p);
}
- if (root == null) {
+ if (r == null) {
prevNode.p = srem;
} else {
- ConsAltNode.listAdd(root, srem);
+ ConsAltNode.listAdd(r, srem);
}
}
/* ending */
- Node xnode = topRoot != null ? topRoot : prevNode.p;
+ final Node xnode = topRoot != null ? topRoot : prevNode.p;
swap(node, xnode);
return xnode;
@@ -910,7 +982,10 @@ final class Analyser extends Parser {
5. find invalid patterns in look-behind.
6. expand repeated string.
*/
- protected final Node setupTree(Node node, int state) {
+ protected final Node setupTree(final Node nodep, final int statep) {
+ Node node = nodep;
+ int state = statep;
+
restart: while (true) {
switch (node.getType()) {
case NodeType.LIST:
@@ -946,7 +1021,7 @@ final class Analyser extends Parser {
break;
case NodeType.BREF:
- BackRefNode br = (BackRefNode)node;
+ final BackRefNode br = (BackRefNode)node;
if (br.backRef > env.numMem) {
throw new ValueException(ERR_INVALID_BACKREF);
}
@@ -956,25 +1031,31 @@ final class Analyser extends Parser {
break;
case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
+ final QuantifierNode qn = (QuantifierNode)node;
Node target = qn.target;
- if ((state & IN_REPEAT) != 0) qn.setInRepeat();
+ if ((state & IN_REPEAT) != 0) {
+ qn.setInRepeat();
+ }
if (isRepeatInfinite(qn.upper) || qn.lower >= 1) {
- int d = getMinMatchLength(target);
+ final int d = getMinMatchLength(target);
if (d == 0) {
qn.targetEmptyInfo = TargetInfo.IS_EMPTY;
if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
- int info = quantifiersMemoryInfo(target);
- if (info > 0) qn.targetEmptyInfo = info;
+ final int info = quantifiersMemoryInfo(target);
+ if (info > 0) {
+ qn.targetEmptyInfo = info;
+ }
} // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
// strange stuff here (turned off)
}
}
state |= IN_REPEAT;
- if (qn.lower != qn.upper) state |= IN_VAR_REPEAT;
+ if (qn.lower != qn.upper) {
+ state |= IN_VAR_REPEAT;
+ }
target = setupTree(target, state);
@@ -982,12 +1063,12 @@ final class Analyser extends Parser {
if (target.getType() == NodeType.STR) {
if (!isRepeatInfinite(qn.lower) && qn.lower == qn.upper &&
qn.lower > 1 && qn.lower <= EXPAND_STRING_MAX_LENGTH) {
- StringNode sn = (StringNode)target;
- int len = sn.length();
+ final StringNode sn = (StringNode)target;
+ final int len = sn.length();
if (len * qn.lower <= EXPAND_STRING_MAX_LENGTH) {
- StringNode str = qn.convertToString(sn.flag);
- int n = qn.lower;
+ final StringNode str = qn.convertToString(sn.flag);
+ final int n = qn.lower;
for (int i = 0; i < n; i++) {
str.cat(sn.chars, sn.p, sn.end);
}
@@ -999,7 +1080,7 @@ final class Analyser extends Parser {
if (Config.USE_OP_PUSH_OR_JUMP_EXACT) {
if (qn.greedy && qn.targetEmptyInfo != 0) {
if (target.getType() == NodeType.QTFR) {
- QuantifierNode tqn = (QuantifierNode)target;
+ final QuantifierNode tqn = (QuantifierNode)target;
if (tqn.headExact != null) {
qn.headExact = tqn.headExact;
tqn.headExact = null;
@@ -1012,10 +1093,10 @@ final class Analyser extends Parser {
break;
case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.OPTION:
- int options = regex.options;
+ final int options = regex.options;
regex.options = en.option;
setupTree(en.target, state);
regex.options = options;
@@ -1033,19 +1114,24 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
setupTree(en.target, state);
if (en.target.getType() == NodeType.QTFR) {
- QuantifierNode tqn = (QuantifierNode)en.target;
+ final QuantifierNode tqn = (QuantifierNode)en.target;
if (isRepeatInfinite(tqn.upper) && tqn.lower <= 1 && tqn.greedy) {
/* (?>a*), a*+ etc... */
- if (tqn.target.isSimple()) en.setStopBtSimpleRepeat();
+ if (tqn.target.isSimple()) {
+ en.setStopBtSimpleRepeat();
+ }
}
}
break;
+ default:
+ break;
+
} // inner switch
break;
case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
+ final AnchorNode an = (AnchorNode)node;
switch (an.type) {
case AnchorType.PREC_READ:
setupTree(an.target, state);
@@ -1060,7 +1146,9 @@ final class Analyser extends Parser {
throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
}
node = setupLookBehind(node);
- if (node.getType() != NodeType.ANCHOR) continue restart;
+ if (node.getType() != NodeType.ANCHOR) {
+ continue restart;
+ }
setupTree(((AnchorNode)node).target, state);
break;
@@ -1069,26 +1157,33 @@ final class Analyser extends Parser {
throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
}
node = setupLookBehind(node);
- if (node.getType() != NodeType.ANCHOR) continue restart;
+ if (node.getType() != NodeType.ANCHOR) {
+ continue restart;
+ }
setupTree(((AnchorNode)node).target, (state | IN_NOT));
break;
+ default:
+ break;
+
} // inner switch
break;
+ default:
+ break;
} // switch
return node;
} // restart: while
}
private static final int MAX_NODE_OPT_INFO_REF_COUNT = 5;
- private void optimizeNodeLeft(Node node, NodeOptInfo opt, OptEnvironment oenv) { // oenv remove, pass mmd
+ private void optimizeNodeLeft(final Node node, final NodeOptInfo opt, final OptEnvironment oenv) { // oenv remove, pass mmd
opt.clear();
opt.setBoundNode(oenv.mmd);
switch (node.getType()) {
case NodeType.LIST: {
- OptEnvironment nenv = new OptEnvironment();
- NodeOptInfo nopt = new NodeOptInfo();
+ final OptEnvironment nenv = new OptEnvironment();
+ final NodeOptInfo nopt = new NodeOptInfo();
nenv.copy(oenv);
ConsAltNode lin = (ConsAltNode)node;
do {
@@ -1100,7 +1195,7 @@ final class Analyser extends Parser {
}
case NodeType.ALT: {
- NodeOptInfo nopt = new NodeOptInfo();
+ final NodeOptInfo nopt = new NodeOptInfo();
ConsAltNode aln = (ConsAltNode)node;
do {
optimizeNodeLeft(aln.car, nopt, oenv);
@@ -1114,9 +1209,9 @@ final class Analyser extends Parser {
}
case NodeType.STR: {
- StringNode sn = (StringNode)node;
+ final StringNode sn = (StringNode)node;
- int slen = sn.length();
+ final int slen = sn.length();
if (!sn.isAmbig()) {
opt.exb.concatStr(sn.chars, sn.p, sn.end, sn.isRaw());
@@ -1150,13 +1245,13 @@ final class Analyser extends Parser {
}
case NodeType.CCLASS: {
- CClassNode cc = (CClassNode)node;
+ final CClassNode cc = (CClassNode)node;
/* no need to check ignore case. (setted in setup_tree()) */
if (cc.mbuf != null || cc.isNot()) {
opt.length.set(1, 1);
} else {
for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
- boolean z = cc.bs.at(i);
+ final boolean z = cc.bs.at(i);
if ((z && !cc.isNot()) || (!z && cc.isNot())) {
opt.map.addChar(i);
}
@@ -1172,7 +1267,7 @@ final class Analyser extends Parser {
}
case NodeType.ANCHOR: {
- AnchorNode an = (AnchorNode)node;
+ final AnchorNode an = (AnchorNode)node;
switch (an.type) {
case AnchorType.BEGIN_BUF:
case AnchorType.BEGIN_POSITION:
@@ -1184,7 +1279,7 @@ final class Analyser extends Parser {
break;
case AnchorType.PREC_READ:
- NodeOptInfo nopt = new NodeOptInfo();
+ final NodeOptInfo nopt = new NodeOptInfo();
optimizeNodeLeft(an.target, nopt, oenv);
if (nopt.exb.length > 0) {
opt.expr.copy(nopt.exb);
@@ -1192,7 +1287,9 @@ final class Analyser extends Parser {
opt.expr.copy(nopt.exm);
}
opt.expr.reachEnd = false;
- if (nopt.map.value > 0) opt.map.copy(nopt.map);
+ if (nopt.map.value > 0) {
+ opt.map.copy(nopt.map);
+ }
break;
case AnchorType.PREC_READ_NOT:
@@ -1200,22 +1297,25 @@ final class Analyser extends Parser {
case AnchorType.LOOK_BEHIND_NOT:
break;
+ default:
+ break;
+
} // inner switch
break;
}
case NodeType.BREF: {
- BackRefNode br = (BackRefNode)node;
+ final BackRefNode br = (BackRefNode)node;
if (br.isRecursion()) {
opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
break;
}
- Node[]nodes = oenv.scanEnv.memNodes;
+ final Node[]nodes = oenv.scanEnv.memNodes;
- int min = getMinMatchLength(nodes[br.backRef]);
- int max = getMaxMatchLength(nodes[br.backRef]);
+ final int min = getMinMatchLength(nodes[br.backRef]);
+ final int max = getMaxMatchLength(nodes[br.backRef]);
opt.length.set(min, max);
break;
@@ -1223,8 +1323,8 @@ final class Analyser extends Parser {
case NodeType.QTFR: {
- NodeOptInfo nopt = new NodeOptInfo();
- QuantifierNode qn = (QuantifierNode)node;
+ final NodeOptInfo nopt = new NodeOptInfo();
+ final QuantifierNode qn = (QuantifierNode)node;
optimizeNodeLeft(qn.target, nopt, oenv);
if (qn.lower == 0 && isRepeatInfinite(qn.upper)) {
if (oenv.mmd.max == 0 && qn.target.getType() == NodeType.CANY && qn.greedy) {
@@ -1258,7 +1358,7 @@ final class Analyser extends Parser {
}
}
- int min = MinMaxLen.distanceMultiply(nopt.length.min, qn.lower);
+ final int min = MinMaxLen.distanceMultiply(nopt.length.min, qn.lower);
int max;
if (isRepeatInfinite(qn.upper)) {
max = nopt.length.max > 0 ? MinMaxLen.INFINITE_DISTANCE : 0;
@@ -1270,10 +1370,10 @@ final class Analyser extends Parser {
}
case NodeType.ENCLOSE: {
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.OPTION:
- int save = oenv.options;
+ final int save = oenv.options;
oenv.options = en.option;
optimizeNodeLeft(en.target, opt, oenv);
oenv.options = save;
@@ -1283,8 +1383,12 @@ final class Analyser extends Parser {
if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
int min = 0;
int max = MinMaxLen.INFINITE_DISTANCE;
- if (en.isMinFixed()) min = en.minLength;
- if (en.isMaxFixed()) max = en.maxLength;
+ if (en.isMinFixed()) {
+ min = en.minLength;
+ }
+ if (en.isMaxFixed()) {
+ max = en.maxLength;
+ }
opt.length.set(min, max);
} else { // USE_SUBEXP_CALL
optimizeNodeLeft(en.target, opt, oenv);
@@ -1299,6 +1403,9 @@ final class Analyser extends Parser {
case EncloseType.STOP_BACKTRACK:
optimizeNodeLeft(en.target, opt, oenv);
break;
+
+ default:
+ break;
} // inner switch
break;
}
@@ -1308,9 +1415,10 @@ final class Analyser extends Parser {
} // switch
}
- protected final void setOptimizedInfoFromTree(Node node) {
- NodeOptInfo opt = new NodeOptInfo();
- OptEnvironment oenv = new OptEnvironment();
+ @SuppressWarnings("unused")
+ protected final void setOptimizedInfoFromTree(final Node node) {
+ final NodeOptInfo opt = new NodeOptInfo();
+ final OptEnvironment oenv = new OptEnvironment();
oenv.options = regex.options;
oenv.caseFoldFlag = regex.caseFoldFlag;
@@ -1348,7 +1456,9 @@ final class Analyser extends Parser {
regex.setSubAnchor(opt.map.anchor);
} else {
regex.subAnchor |= opt.anchor.leftAnchor & AnchorType.BEGIN_LINE;
- if (opt.length.max == 0) regex.subAnchor |= opt.anchor.rightAnchor & AnchorType.END_LINE;
+ if (opt.length.max == 0) {
+ regex.subAnchor |= opt.anchor.rightAnchor & AnchorType.END_LINE;
+ }
}
if (Config.DEBUG_COMPILE || Config.DEBUG_MATCH) {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
index dda5b733..5ecfec4f 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
@@ -24,14 +24,14 @@ import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
final class ApplyCaseFold {
// i_apply_case_fold
- public void apply(int from, int to, Object o) {
- ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o;
+ public static void apply(final int from, final int to, final Object o) {
+ final ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o;
- ScanEnvironment env = arg.env;
- CClassNode cc = arg.cc;
- BitSet bs = cc.bs;
+ final ScanEnvironment env = arg.env;
+ final CClassNode cc = arg.cc;
+ final BitSet bs = cc.bs;
- boolean inCC = cc.isCodeInCC(from);
+ final boolean inCC = cc.isCodeInCC(from);
if (Config.CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS) {
if ((inCC && !cc.isNot()) || (!inCC && cc.isNot())) {
@@ -45,7 +45,9 @@ final class ApplyCaseFold {
} else {
if (inCC) {
if (to >= BitSet.SINGLE_BYTE_SIZE) {
- if (cc.isNot()) cc.clearNotFlag();
+ if (cc.isNot()) {
+ cc.clearNotFlag();
+ }
cc.addCodeRange(env, to, to);
} else {
if (cc.isNot()) {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
index e991aed1..ce25af62 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
@@ -22,13 +22,14 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
+@SuppressWarnings("javadoc")
public final class ApplyCaseFoldArg {
final ScanEnvironment env;
final CClassNode cc;
ConsAltNode altRoot;
ConsAltNode tail;
- public ApplyCaseFoldArg(ScanEnvironment env, CClassNode cc) {
+ public ApplyCaseFoldArg(final ScanEnvironment env, final CClassNode cc) {
this.env = env;
this.cc = cc;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
index 33d56c17..0e789333 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
@@ -24,7 +24,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDynamic;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
@@ -47,13 +46,13 @@ final class ArrayCompiler extends Compiler {
private char[][] templates;
private int templateNum;
- ArrayCompiler(Analyser analyser) {
+ ArrayCompiler(final Analyser analyser) {
super(analyser);
}
@Override
protected final void prepare() {
- int codeSize = Config.USE_STRING_TEMPLATES ? 8 : ((analyser.getEnd() - analyser.getBegin()) * 2 + 2);
+ final int codeSize = Config.USE_STRING_TEMPLATES ? 8 : ((analyser.getEnd() - analyser.getBegin()) * 2 + 2);
code = new int[codeSize];
codeLength = 0;
}
@@ -71,7 +70,7 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileAltNode(ConsAltNode node) {
+ protected void compileAltNode(final ConsAltNode node) {
ConsAltNode aln = node;
int len = 0;
@@ -82,7 +81,7 @@ final class ArrayCompiler extends Compiler {
}
} while ((aln = aln.cdr) != null);
- int pos = codeLength + len; /* goal position */
+ final int pos = codeLength + len; /* goal position */
aln = node;
do {
@@ -98,15 +97,15 @@ final class ArrayCompiler extends Compiler {
} while ((aln = aln.cdr) != null);
}
- private boolean isNeedStrLenOpExact(int op) {
+ private static boolean isNeedStrLenOpExact(final int op) {
return op == OPCode.EXACTN || op == OPCode.EXACTN_IC;
}
- private boolean opTemplated(int op) {
+ private static boolean opTemplated(final int op) {
return isNeedStrLenOpExact(op);
}
- private int selectStrOpcode(int strLength, boolean ignoreCase) {
+ private static int selectStrOpcode(final int strLength, final boolean ignoreCase) {
int op;
if (ignoreCase) {
@@ -127,8 +126,8 @@ final class ArrayCompiler extends Compiler {
return op;
}
- private void compileTreeEmptyCheck(Node node, int emptyInfo) {
- int savedNumNullCheck = regex.numNullCheck;
+ private void compileTreeEmptyCheck(final Node node, final int emptyInfo) {
+ final int savedNumNullCheck = regex.numNullCheck;
if (emptyInfo != 0) {
addOpcode(OPCode.NULL_CHECK_START);
@@ -139,7 +138,7 @@ final class ArrayCompiler extends Compiler {
compileTree(node);
if (emptyInfo != 0) {
- switch(emptyInfo) {
+ switch (emptyInfo) {
case TargetInfo.IS_EMPTY:
addOpcode(OPCode.NULL_CHECK_END);
break;
@@ -149,29 +148,33 @@ final class ArrayCompiler extends Compiler {
case TargetInfo.IS_EMPTY_REC:
addOpcode(OPCode.NULL_CHECK_END_MEMST_PUSH);
break;
+ default:
+ break;
} // switch
addMemNum(savedNumNullCheck); /* NULL CHECK ID */
}
}
- private int addCompileStringlength(char[] chars, int p, int strLength, boolean ignoreCase) {
- int op = selectStrOpcode(strLength, ignoreCase);
+ private static int addCompileStringlength(final char[] chars, final int p, final int strLength, final boolean ignoreCase) {
+ final int op = selectStrOpcode(strLength, ignoreCase);
int len = OPSize.OPCODE;
if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
// string length, template index, template string pointer
len += OPSize.LENGTH + OPSize.INDEX + OPSize.INDEX;
} else {
- if (isNeedStrLenOpExact(op)) len += OPSize.LENGTH;
+ if (isNeedStrLenOpExact(op)) {
+ len += OPSize.LENGTH;
+ }
len += strLength;
}
return len;
}
@Override
- protected final void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase) {
- int op = selectStrOpcode(strLength, ignoreCase);
+ protected final void addCompileString(final char[] chars, final int p, final int strLength, final boolean ignoreCase) {
+ final int op = selectStrOpcode(strLength, ignoreCase);
addOpcode(op);
if (isNeedStrLenOpExact(op)) {
@@ -187,15 +190,17 @@ final class ArrayCompiler extends Compiler {
}
}
- private int compileLengthStringNode(Node node) {
- StringNode sn = (StringNode)node;
- if (sn.length() <= 0) return 0;
- boolean ambig = sn.isAmbig();
+ private static int compileLengthStringNode(final Node node) {
+ final StringNode sn = (StringNode)node;
+ if (sn.length() <= 0) {
+ return 0;
+ }
+ final boolean ambig = sn.isAmbig();
int p, prev;
p = prev = sn.p;
- int end = sn.end;
- char[] chars = sn.chars;
+ final int end = sn.end;
+ final char[] chars = sn.chars;
p++;
int slen = 1;
@@ -205,23 +210,27 @@ final class ArrayCompiler extends Compiler {
slen++;
p++;
}
- int r = addCompileStringlength(chars, prev, slen, ambig);
+ final int r = addCompileStringlength(chars, prev, slen, ambig);
rlen += r;
return rlen;
}
- private int compileLengthStringRawNode(StringNode sn) {
- if (sn.length() <= 0) return 0;
+ private static int compileLengthStringRawNode(final StringNode sn) {
+ if (sn.length() <= 0) {
+ return 0;
+ }
return addCompileStringlength(sn.chars, sn.p, sn.length(), false);
}
- private void addMultiByteCClass(CodeRangeBuffer mbuf) {
+ private void addMultiByteCClass(final CodeRangeBuffer mbuf) {
addLength(mbuf.used);
addInts(mbuf.p, mbuf.used);
}
- private int compileLengthCClassNode(CClassNode cc) {
- if (cc.isShare()) return OPSize.OPCODE + OPSize.POINTER;
+ private static int compileLengthCClassNode(final CClassNode cc) {
+ if (cc.isShare()) {
+ return OPSize.OPCODE + OPSize.POINTER;
+ }
int len;
if (cc.mbuf == null) {
@@ -239,7 +248,7 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileCClassNode(CClassNode cc) {
+ protected void compileCClassNode(final CClassNode cc) {
if (cc.isShare()) { // shared char class
addOpcode(OPCode.CCLASS_NODE);
addPointer(cc);
@@ -284,7 +293,7 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileBackrefNode(BackRefNode node) {
+ protected void compileBackrefNode(final BackRefNode node) {
if (isIgnoreCase(regex.options)) {
addOpcode(OPCode.BACKREFN_IC);
addMemNum(node.backRef);
@@ -305,7 +314,7 @@ final class ArrayCompiler extends Compiler {
}
private static final int REPEAT_RANGE_ALLOC = 8;
- private void entryRepeatRange(int id, int lower, int upper) {
+ private void entryRepeatRange(final int id, final int lower, final int upper) {
if (regex.repeatRangeLo == null) {
regex.repeatRangeLo = new int[REPEAT_RANGE_ALLOC];
regex.repeatRangeHi = new int[REPEAT_RANGE_ALLOC];
@@ -322,8 +331,8 @@ final class ArrayCompiler extends Compiler {
regex.repeatRangeHi[id] = isRepeatInfinite(upper) ? 0x7fffffff : upper;
}
- private void compileRangeRepeatNode(QuantifierNode qn, int targetLen, int emptyInfo) {
- int numRepeat = regex.numRepeat;
+ private void compileRangeRepeatNode(final QuantifierNode qn, final int targetLen, final int emptyInfo) {
+ final int numRepeat = regex.numRepeat;
addOpcode(qn.greedy ? OPCode.REPEAT : OPCode.REPEAT_NG);
addMemNum(numRepeat); /* OP_REPEAT ID */
regex.numRepeat++;
@@ -345,24 +354,23 @@ final class ArrayCompiler extends Compiler {
private static final int QUANTIFIER_EXPAND_LIMIT_SIZE = 50; // was 50
@SuppressWarnings("unused")
- private static boolean cknOn(int ckn) {
+ private static boolean cknOn(final int ckn) {
return ckn > 0;
}
- private int compileNonCECLengthQuantifierNode(QuantifierNode qn) {
- boolean infinite = isRepeatInfinite(qn.upper);
- int emptyInfo = qn.targetEmptyInfo;
+ private int compileNonCECLengthQuantifierNode(final QuantifierNode qn) {
+ final boolean infinite = isRepeatInfinite(qn.upper);
+ final int emptyInfo = qn.targetEmptyInfo;
- int tlen = compileLengthTree(qn.target);
+ final int tlen = compileLengthTree(qn.target);
/* anychar repeat */
if (qn.target.getType() == NodeType.CANY) {
if (qn.greedy && infinite) {
if (qn.nextHeadExact != null) {
return OPSize.ANYCHAR_STAR_PEEK_NEXT + tlen * qn.lower;
- } else {
- return OPSize.ANYCHAR_STAR + tlen * qn.lower;
}
+ return OPSize.ANYCHAR_STAR + tlen * qn.lower;
}
}
@@ -408,11 +416,11 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileNonCECQuantifierNode(QuantifierNode qn) {
- boolean infinite = isRepeatInfinite(qn.upper);
- int emptyInfo = qn.targetEmptyInfo;
+ protected void compileNonCECQuantifierNode(final QuantifierNode qn) {
+ final boolean infinite = isRepeatInfinite(qn.upper);
+ final int emptyInfo = qn.targetEmptyInfo;
- int tlen = compileLengthTree(qn.target);
+ final int tlen = compileLengthTree(qn.target);
if (qn.isAnyCharStar()) {
compileTreeNTimes(qn.target, qn.lower);
@@ -422,17 +430,16 @@ final class ArrayCompiler extends Compiler {
} else {
addOpcode(OPCode.ANYCHAR_STAR_PEEK_NEXT);
}
- StringNode sn = (StringNode)qn.nextHeadExact;
+ final StringNode sn = (StringNode)qn.nextHeadExact;
addChars(sn.chars, sn.p, 1);
return;
+ }
+ if (isMultiline(regex.options)) {
+ addOpcode(OPCode.ANYCHAR_ML_STAR);
} else {
- if (isMultiline(regex.options)) {
- addOpcode(OPCode.ANYCHAR_ML_STAR);
- } else {
- addOpcode(OPCode.ANYCHAR_STAR);
- }
- return;
+ addOpcode(OPCode.ANYCHAR_STAR);
}
+ return;
}
int modTLen;
@@ -461,13 +468,13 @@ final class ArrayCompiler extends Compiler {
if (qn.greedy) {
if (qn.headExact != null) {
addOpcodeRelAddr(OPCode.PUSH_OR_JUMP_EXACT1, modTLen + OPSize.JUMP);
- StringNode sn = (StringNode)qn.headExact;
+ final StringNode sn = (StringNode)qn.headExact;
addChars(sn.chars, sn.p, 1);
compileTreeEmptyCheck(qn.target, emptyInfo);
addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + OPSize.PUSH_OR_JUMP_EXACT1));
} else if (qn.nextHeadExact != null) {
addOpcodeRelAddr(OPCode.PUSH_IF_PEEK_NEXT, modTLen + OPSize.JUMP);
- StringNode sn = (StringNode)qn.nextHeadExact;
+ final StringNode sn = (StringNode)qn.nextHeadExact;
addChars(sn.chars, sn.p, 1);
compileTreeEmptyCheck(qn.target, emptyInfo);
addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + OPSize.PUSH_IF_PEEK_NEXT));
@@ -486,7 +493,7 @@ final class ArrayCompiler extends Compiler {
compileTree(qn.target);
} else if (!infinite && qn.greedy &&
(qn.upper == 1 || (tlen + OPSize.PUSH) * qn.upper <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
- int n = qn.upper - qn.lower;
+ final int n = qn.upper - qn.lower;
compileTreeNTimes(qn.target, qn.lower);
for (int i=0; i<n; i++) {
@@ -502,22 +509,21 @@ final class ArrayCompiler extends Compiler {
}
}
- private int compileLengthOptionNode(EncloseNode node) {
- int prev = regex.options;
+ private int compileLengthOptionNode(final EncloseNode node) {
+ final int prev = regex.options;
regex.options = node.option;
- int tlen = compileLengthTree(node.target);
+ final int tlen = compileLengthTree(node.target);
regex.options = prev;
if (isDynamic(prev ^ node.option)) {
return OPSize.SET_OPTION_PUSH + OPSize.SET_OPTION + OPSize.FAIL + tlen + OPSize.SET_OPTION;
- } else {
- return tlen;
}
+ return tlen;
}
@Override
- protected void compileOptionNode(EncloseNode node) {
- int prev = regex.options;
+ protected void compileOptionNode(final EncloseNode node) {
+ final int prev = regex.options;
if (isDynamic(prev ^ node.option)) {
addOpcodeOption(OPCode.SET_OPTION_PUSH, node.option);
@@ -534,7 +540,7 @@ final class ArrayCompiler extends Compiler {
}
}
- private int compileLengthEncloseNode(EncloseNode node) {
+ private int compileLengthEncloseNode(final EncloseNode node) {
if (node.isOption()) {
return compileLengthOptionNode(node);
}
@@ -559,7 +565,7 @@ final class ArrayCompiler extends Compiler {
case EncloseType.STOP_BACKTRACK:
if (node.isStopBtSimpleRepeat()) {
- QuantifierNode qn = (QuantifierNode)node.target;
+ final QuantifierNode qn = (QuantifierNode)node.target;
tlen = compileLengthTree(qn.target);
len = tlen * qn.lower + OPSize.PUSH + tlen + OPSize.POP + OPSize.JUMP;
} else {
@@ -575,7 +581,7 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileEncloseNode(EncloseNode node) {
+ protected void compileEncloseNode(final EncloseNode node) {
int len;
switch (node.type) {
case EncloseType.MEMORY:
@@ -598,7 +604,7 @@ final class ArrayCompiler extends Compiler {
case EncloseType.STOP_BACKTRACK:
if (node.isStopBtSimpleRepeat()) {
- QuantifierNode qn = (QuantifierNode)node.target;
+ final QuantifierNode qn = (QuantifierNode)node.target;
compileTreeNTimes(qn.target, qn.lower);
@@ -620,7 +626,7 @@ final class ArrayCompiler extends Compiler {
} // switch
}
- private int compileLengthAnchorNode(AnchorNode node) {
+ private int compileLengthAnchorNode(final AnchorNode node) {
int tlen;
if (node.target != null) {
tlen = compileLengthTree(node.target);
@@ -654,7 +660,7 @@ final class ArrayCompiler extends Compiler {
}
@Override
- protected void compileAnchorNode(AnchorNode node) {
+ protected void compileAnchorNode(final AnchorNode node) {
int len;
int n;
@@ -675,13 +681,15 @@ final class ArrayCompiler extends Compiler {
break;
case AnchorType.WORD_BEGIN:
- if (Config.USE_WORD_BEGIN_END)
+ if (Config.USE_WORD_BEGIN_END) {
addOpcode(OPCode.WORD_BEGIN);
+ }
break;
case AnchorType.WORD_END:
- if (Config.USE_WORD_BEGIN_END)
+ if (Config.USE_WORD_BEGIN_END) {
addOpcode(OPCode.WORD_END);
+ }
break;
case AnchorType.PREC_READ:
@@ -701,7 +709,9 @@ final class ArrayCompiler extends Compiler {
addOpcode(OPCode.LOOK_BEHIND);
if (node.charLength < 0) {
n = analyser.getCharLengthTree(node.target);
- if (analyser.returnCode != 0) newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
+ if (analyser.returnCode != 0) {
+ newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
+ }
} else {
n = node.charLength;
}
@@ -714,7 +724,9 @@ final class ArrayCompiler extends Compiler {
addOpcodeRelAddr(OPCode.PUSH_LOOK_BEHIND_NOT, len + OPSize.FAIL_LOOK_BEHIND_NOT);
if (node.charLength < 0) {
n = analyser.getCharLengthTree(node.target);
- if (analyser.returnCode != 0) newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
+ if (analyser.returnCode != 0) {
+ newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN);
+ }
} else {
n = node.charLength;
}
@@ -728,7 +740,7 @@ final class ArrayCompiler extends Compiler {
} // switch
}
- private int compileLengthTree(Node node) {
+ private int compileLengthTree(final Node node) {
int len = 0;
switch (node.getType()) {
@@ -750,7 +762,7 @@ final class ArrayCompiler extends Compiler {
break;
case NodeType.STR:
- StringNode sn = (StringNode)node;
+ final StringNode sn = (StringNode)node;
if (sn.isRaw()) {
len = compileLengthStringRawNode(sn);
} else {
@@ -768,7 +780,7 @@ final class ArrayCompiler extends Compiler {
break;
case NodeType.BREF:
- BackRefNode br = (BackRefNode)node;
+ final BackRefNode br = (BackRefNode)node;
len = ((!isIgnoreCase(regex.options) && br.backRef <= 2)
? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
@@ -793,35 +805,37 @@ final class ArrayCompiler extends Compiler {
return len;
}
- private void ensure(int size) {
+ private void ensure(final int size) {
if (size >= code.length) {
int length = code.length << 1;
- while (length <= size) length <<= 1;
- int[]tmp = new int[length];
+ while (length <= size) {
+ length <<= 1;
+ }
+ final int[]tmp = new int[length];
System.arraycopy(code, 0, tmp, 0, code.length);
code = tmp;
}
}
- private void addInt(int i) {
+ private void addInt(final int i) {
if (codeLength >= code.length) {
- int[]tmp = new int[code.length << 1];
+ final int[]tmp = new int[code.length << 1];
System.arraycopy(code, 0, tmp, 0, code.length);
code = tmp;
}
code[codeLength++] = i;
}
- void setInt(int i, int offset) {
+ void setInt(final int i, final int offset) {
ensure(offset);
regex.code[offset] = i;
}
- private void addObject(Object o) {
+ private void addObject(final Object o) {
if (regex.operands == null) {
regex.operands = new Object[4];
} else if (regex.operandLength >= regex.operands.length) {
- Object[]tmp = new Object[regex.operands.length << 1];
+ final Object[]tmp = new Object[regex.operands.length << 1];
System.arraycopy(regex.operands, 0, tmp, 0, regex.operands.length);
regex.operands = tmp;
}
@@ -829,20 +843,23 @@ final class ArrayCompiler extends Compiler {
regex.operands[regex.operandLength++] = o;
}
- private void addChars(char[] chars, int p ,int length) {
+ private void addChars(final char[] chars, final int pp ,final int length) {
ensure(codeLength + length);
- int end = p + length;
+ int p = pp;
+ final int end = p + length;
- while (p < end) code[codeLength++] = chars[p++];
+ while (p < end) {
+ code[codeLength++] = chars[p++];
+ }
}
- private void addInts(int[]ints, int length) {
+ private void addInts(final int[]ints, final int length) {
ensure(codeLength + length);
System.arraycopy(ints, 0, code, codeLength, length);
codeLength += length;
}
- private void addOpcode(int opcode) {
+ private void addOpcode(final int opcode) {
addInt(opcode);
switch(opcode) {
@@ -876,54 +893,57 @@ final class ArrayCompiler extends Compiler {
case OPCode.CALL:
case OPCode.RETURN: // it will appear only with CALL though
regex.stackNeeded = true;
+ break;
+ default:
+ break;
}
}
@SuppressWarnings("unused")
- private void addStateCheckNum(int num) {
+ private void addStateCheckNum(final int num) {
addInt(num);
}
- private void addRelAddr(int addr) {
+ private void addRelAddr(final int addr) {
addInt(addr);
}
@SuppressWarnings("unused")
- private void addAbsAddr(int addr) {
+ private void addAbsAddr(final int addr) {
addInt(addr);
}
- private void addLength(int length) {
+ private void addLength(final int length) {
addInt(length);
}
- private void addMemNum(int num) {
+ private void addMemNum(final int num) {
addInt(num);
}
- private void addPointer(Object o) {
+ private void addPointer(final Object o) {
addObject(o);
}
- private void addOption(int option) {
+ private void addOption(final int option) {
addInt(option);
}
- private void addOpcodeRelAddr(int opcode, int addr) {
+ private void addOpcodeRelAddr(final int opcode, final int addr) {
addOpcode(opcode);
addRelAddr(addr);
}
- private void addOpcodeOption(int opcode, int option) {
+ private void addOpcodeOption(final int opcode, final int option) {
addOpcode(opcode);
addOption(option);
}
- private void addTemplate(char[] chars) {
+ private void addTemplate(final char[] chars) {
if (templateNum == 0) {
templates = new char[2][];
} else if (templateNum == templates.length) {
- char[][] tmp = new char[templateNum * 2][];
+ final char[][] tmp = new char[templateNum * 2][];
System.arraycopy(templates, 0, tmp, 0, templateNum);
templates = tmp;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java b/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
index 58ec56d6..2747c24c 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public final class BitSet {
static final int BITS_PER_BYTE = 8;
public static final int SINGLE_BYTE_SIZE = (1 << BITS_PER_BYTE);
@@ -31,77 +32,100 @@ public final class BitSet {
private static final int BITS_TO_STRING_WRAP = 4;
@Override
public String toString() {
- StringBuilder buffer = new StringBuilder();
+ final StringBuilder buffer = new StringBuilder();
buffer.append("BitSet");
for (int i=0; i<SINGLE_BYTE_SIZE; i++) {
- if ((i % (SINGLE_BYTE_SIZE / BITS_TO_STRING_WRAP)) == 0) buffer.append("\n ");
+ if ((i % (SINGLE_BYTE_SIZE / BITS_TO_STRING_WRAP)) == 0) {
+ buffer.append("\n ");
+ }
buffer.append(at(i) ? "1" : "0");
}
return buffer.toString();
}
- public boolean at(int pos) {
+ public boolean at(final int pos) {
return (bits[pos >>> ROOM_SHIFT] & bit(pos)) != 0;
}
- public void set(int pos) {
+ public void set(final int pos) {
bits[pos >>> ROOM_SHIFT] |= bit(pos);
}
- public void clear(int pos) {
+ public void clear(final int pos) {
bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
}
public void clear() {
- for (int i=0; i<BITSET_SIZE; i++) bits[i]=0;
+ for (int i=0; i<BITSET_SIZE; i++) {
+ bits[i]=0;
+ }
}
public boolean isEmpty() {
for (int i=0; i<BITSET_SIZE; i++) {
- if (bits[i] != 0) return false;
+ if (bits[i] != 0) {
+ return false;
+ }
}
return true;
}
- public void setRange(int from, int to) {
- for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i);
+ public void setRange(final int from, final int to) {
+ for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) {
+ set(i);
+ }
}
public void invert() {
- for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i];
+ for (int i=0; i<BITSET_SIZE; i++) {
+ bits[i] = ~bits[i];
+ }
}
- public void invertTo(BitSet to) {
- for (int i=0; i<BITSET_SIZE; i++) to.bits[i] = ~bits[i];
+ public void invertTo(final BitSet to) {
+ for (int i=0; i<BITSET_SIZE; i++) {
+ to.bits[i] = ~bits[i];
+ }
}
- public void and(BitSet other) {
- for (int i=0; i<BITSET_SIZE; i++) bits[i] &= other.bits[i];
+ public void and(final BitSet other) {
+ for (int i=0; i<BITSET_SIZE; i++) {
+ bits[i] &= other.bits[i];
+ }
}
- public void or(BitSet other) {
- for (int i=0; i<BITSET_SIZE; i++) bits[i] |= other.bits[i];
+ public void or(final BitSet other) {
+ for (int i=0; i<BITSET_SIZE; i++) {
+ bits[i] |= other.bits[i];
+ }
}
- public void copy(BitSet other) {
- for (int i=0; i<BITSET_SIZE; i++) bits[i] = other.bits[i];
+ public void copy(final BitSet other) {
+ for (int i=0; i<BITSET_SIZE; i++) {
+ bits[i] = other.bits[i];
+ }
}
public int numOn() {
int num = 0;
for (int i=0; i<SINGLE_BYTE_SIZE; i++) {
- if (at(i)) num++;
+ if (at(i)) {
+ num++;
+ }
}
return num;
}
- static int bit(int pos){
+ static int bit(final int pos){
return 1 << (pos % SINGLE_BYTE_SIZE);
}
- private static int log2(int n){
+ private static int log2(final int np) {
int log = 0;
- while ((n >>>= 1) != 0) log++;
+ int n = np;
+ while ((n >>>= 1) != 0) {
+ log++;
+ }
return log;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java b/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
index 30528598..91cf7198 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
@@ -30,11 +30,12 @@ final class BitStatus {
return -1;
}
- public static boolean bsAt(int stats, int n) {
+ public static boolean bsAt(final int stats, final int n) {
return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0;
}
- public static int bsOnAt(int stats, int n) {
+ public static int bsOnAt(final int statsp, final int n) {
+ int stats = statsp;
if (n < BIT_STATUS_BITS_NUM) {
stats |= (1 << n);
} else {
@@ -43,12 +44,7 @@ final class BitStatus {
return stats;
}
- public static int bsOnOff(int v, int f, boolean negative) {
- if (negative) {
- v &= ~f;
- } else {
- v |= f;
- }
- return v;
+ public static int bsOnOff(final int v, final int f, final boolean negative) {
+ return negative ? (v & ~f) : (v | f);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
index b897a8cb..30cfe907 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
@@ -20,17 +20,15 @@
package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
+import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isNewLine;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindLongest;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindNotEmpty;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotBol;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotEol;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isPosixRegion;
-import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isNewLine;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
-import jdk.nashorn.internal.runtime.regexp.joni.constants.OPSize;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
@@ -47,19 +45,19 @@ class ByteCodeMachine extends StackMachine {
private final int[] code; // byte code
private int ip; // instruction pointer
- ByteCodeMachine(Regex regex, char[] chars, int p, int end) {
+ ByteCodeMachine(final Regex regex, final char[] chars, final int p, final int end) {
super(regex, chars, p, end);
this.code = regex.code;
}
- private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) {
-
+ private boolean stringCmpIC(final int caseFlodFlag, final int s1p, final IntHolder ps2, final int mbLen, final int textEnd) {
+ int s1 = s1p;
int s2 = ps2.value;
- int end1 = s1 + mbLen;
+ final int end1 = s1 + mbLen;
while (s1 < end1) {
- char c1 = EncodingHelper.toLowerCase(chars[s1++]);
- char c2 = EncodingHelper.toLowerCase(chars[s2++]);
+ final char c1 = EncodingHelper.toLowerCase(chars[s1++]);
+ final char c2 = EncodingHelper.toLowerCase(chars[s2++]);
if (c1 != c2) {
return false;
@@ -83,41 +81,51 @@ class ByteCodeMachine extends StackMachine {
Config.log.printf("%4d", (s - str)).print("> \"");
int q, i;
for (i=0, q=s; i<7 && q<end && s>=0; i++) {
- if (q < end) Config.log.print(new String(new char[]{chars[q++]}));
+ if (q < end) {
+ Config.log.print(new String(new char[]{chars[q++]}));
+ }
}
- String str = q < end ? "...\"" : "\"";
- q += str.length();
- Config.log.print(str);
- for (i=0; i<20-(q-s);i++) Config.log.print(" ");
- StringBuilder sb = new StringBuilder();
+ final String string = q < end ? "...\"" : "\"";
+ q += string.length();
+ Config.log.print(string);
+ for (i=0; i<20-(q-s);i++) {
+ Config.log.print(" ");
+ }
+ final StringBuilder sb = new StringBuilder();
new ByteCodePrinter(regex).compiledByteCodeToString(sb, ip);
Config.log.println(sb.toString());
}
}
@Override
- protected final int matchAt(int range, int sstart, int sprev) {
- this.range = range;
- this.sstart = sstart;
- this.sprev = sprev;
+ protected final int matchAt(final int r, final int ss, final int sp) {
+ this.range = r;
+ this.sstart = ss;
+ this.sprev = sp;
stk = 0;
ip = 0;
- if (Config.DEBUG_MATCH) debugMatchBegin();
+ if (Config.DEBUG_MATCH) {
+ debugMatchBegin();
+ }
init();
bestLen = -1;
- s = sstart;
+ s = ss;
- final int[]code = this.code;
+ final int[] c = this.code;
while (true) {
- if (Config.DEBUG_MATCH) debugMatchLoop();
+ if (Config.DEBUG_MATCH) {
+ debugMatchLoop();
+ }
sbegin = s;
- switch (code[ip++]) {
- case OPCode.END: if (opEnd()) return finish(); break;
+ switch (c[ip++]) {
+ case OPCode.END: if (opEnd()) {
+ return finish();
+ } break;
case OPCode.EXACT1: opExact1(); break;
case OPCode.EXACT2: opExact2(); continue;
case OPCode.EXACT3: opExact3(); continue;
@@ -215,7 +223,7 @@ class ByteCodeMachine extends StackMachine {
}
private boolean opEnd() {
- int n = s - sstart;
+ final int n = s - sstart;
if (n > bestLen) {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
@@ -259,7 +267,7 @@ class ByteCodeMachine extends StackMachine {
msaEnd = s - str;
}
} else {
- Region region = msaRegion;
+ final Region region = msaRegion;
if (Config.USE_POSIX_API_REGION_OPTION) {
if (!isPosixRegion(regex.options)) {
if (region != null) {
@@ -355,13 +363,17 @@ class ByteCodeMachine extends StackMachine {
if (s + tlen > range) {opFail(); return;}
if (Config.USE_STRING_TEMPLATES) {
- char[] bs = regex.templates[code[ip++]];
+ final char[] bs = regex.templates[code[ip++]];
int ps = code[ip++];
- while (tlen-- > 0) if (bs[ps++] != chars[s++]) {opFail(); return;}
+ while (tlen-- > 0) {
+ if (bs[ps++] != chars[s++]) {opFail(); return;}
+ }
} else {
- while (tlen-- > 0) if (code[ip++] != chars[s++]) {opFail(); return;}
+ while (tlen-- > 0) {
+ if (code[ip++] != chars[s++]) {opFail(); return;}
+ }
}
sprev = s - 1;
}
@@ -377,19 +389,23 @@ class ByteCodeMachine extends StackMachine {
if (s + tlen > range) {opFail(); return;}
if (Config.USE_STRING_TEMPLATES) {
- char[] bs = regex.templates[code[ip++]];
+ final char[] bs = regex.templates[code[ip++]];
int ps = code[ip++];
- while (tlen-- > 0) if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;}
+ while (tlen-- > 0) {
+ if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;}
+ }
} else {
- while (tlen-- > 0) if (code[ip++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;}
+ while (tlen-- > 0) {
+ if (code[ip++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;}
+ }
}
sprev = s - 1;
}
private boolean isInBitSet() {
- int c = chars[s];
+ final int c = chars[s];
return (c <= 0xff && (code[ip + (c >>> BitSet.ROOM_SHIFT)] & (1 << c)) != 0);
}
@@ -401,12 +417,16 @@ class ByteCodeMachine extends StackMachine {
}
private boolean isInClassMB() {
- int tlen = code[ip++];
- if (s >= range) return false;
- int ss = s;
+ final int tlen = code[ip++];
+ if (s >= range) {
+ return false;
+ }
+ final int ss = s;
s++;
- int c = chars[ss];
- if (!EncodingHelper.isInCodeRange(code, ip, c)) return false;
+ final int c = chars[ss];
+ if (!EncodingHelper.isInCodeRange(code, ip, c)) {
+ return false;
+ }
ip += tlen;
return true;
}
@@ -426,7 +446,7 @@ class ByteCodeMachine extends StackMachine {
} else {
if (!isInBitSet()) {opFail(); return;}
ip += BitSet.BITSET_SIZE;
- int tlen = code[ip++]; // by code range length
+ final int tlen = code[ip++]; // by code range length
ip += tlen;
s++;
}
@@ -441,20 +461,24 @@ class ByteCodeMachine extends StackMachine {
}
private boolean isNotInClassMB() {
- int tlen = code[ip++];
+ final int tlen = code[ip++];
if (!(s + 1 <= range)) {
- if (s >= range) return false;
+ if (s >= range) {
+ return false;
+ }
s = end;
ip += tlen;
return true;
}
- int ss = s;
+ final int ss = s;
s++;
- int c = chars[ss];
+ final int c = chars[ss];
- if (EncodingHelper.isInCodeRange(code, ip, c)) return false;
+ if (EncodingHelper.isInCodeRange(code, ip, c)) {
+ return false;
+ }
ip += tlen;
return true;
}
@@ -463,7 +487,7 @@ class ByteCodeMachine extends StackMachine {
if (s >= range) {opFail(); return;}
if (chars[s] <= 0xff) {
s++;
- int tlen = code[ip++];
+ final int tlen = code[ip++];
ip += tlen;
sprev = sbegin; // break;
return;
@@ -480,7 +504,7 @@ class ByteCodeMachine extends StackMachine {
} else {
if (isInBitSet()) {opFail(); return;}
ip += BitSet.BITSET_SIZE;
- int tlen = code[ip++];
+ final int tlen = code[ip++];
ip += tlen;
s++;
}
@@ -489,10 +513,10 @@ class ByteCodeMachine extends StackMachine {
private void opCClassNode() {
if (s >= range) {opFail(); return;}
- CClassNode cc = (CClassNode)regex.operands[code[ip++]];
- int ss = s;
+ final CClassNode cc = (CClassNode)regex.operands[code[ip++]];
+ final int ss = s;
s++;
- int c = chars[ss];
+ final int c = chars[ss];
if (!cc.isCodeInCCLength(c)) {opFail(); return;}
sprev = sbegin; // break;
}
@@ -511,10 +535,10 @@ class ByteCodeMachine extends StackMachine {
}
private void opAnyCharStar() {
- final char[] chars = this.chars;
+ final char[] ch = this.chars;
while (s < range) {
pushAlt(ip, s, sprev);
- if (isNewLine(chars, s, end)) {opFail(); return;}
+ if (isNewLine(ch, s, end)) {opFail(); return;}
sprev = s;
s++;
}
@@ -532,11 +556,13 @@ class ByteCodeMachine extends StackMachine {
private void opAnyCharStarPeekNext() {
final char c = (char)code[ip];
- final char[] chars = this.chars;
+ final char[] ch = this.chars;
while (s < range) {
- char b = chars[s];
- if (c == b) pushAlt(ip + 1, s, sprev);
+ final char b = ch[s];
+ if (c == b) {
+ pushAlt(ip + 1, s, sprev);
+ }
if (isNewLine(b)) {opFail(); return;}
sprev = s;
s++;
@@ -547,10 +573,12 @@ class ByteCodeMachine extends StackMachine {
private void opAnyCharMLStarPeekNext() {
final char c = (char)code[ip];
- final char[] chars = this.chars;
+ final char[] ch = this.chars;
while (s < range) {
- if (c == chars[s]) pushAlt(ip + 1, s, sprev);
+ if (c == ch[s]) {
+ pushAlt(ip + 1, s, sprev);
+ }
sprev = s;
s++;
}
@@ -592,29 +620,39 @@ class ByteCodeMachine extends StackMachine {
private void opWordBegin() {
if (s < range && EncodingHelper.isWord(chars[s])) {
- if (s == str || !EncodingHelper.isWord(chars[sprev])) return;
+ if (s == str || !EncodingHelper.isWord(chars[sprev])) {
+ return;
+ }
}
opFail();
}
private void opWordEnd() {
if (s != str && EncodingHelper.isWord(chars[sprev])) {
- if (s == end || !EncodingHelper.isWord(chars[s])) return;
+ if (s == end || !EncodingHelper.isWord(chars[s])) {
+ return;
+ }
}
opFail();
}
private void opBeginBuf() {
- if (s != str) opFail();
+ if (s != str) {
+ opFail();
+ }
}
private void opEndBuf() {
- if (s != end) opFail();
+ if (s != end) {
+ opFail();
+ }
}
private void opBeginLine() {
if (s == str) {
- if (isNotBol(msaOptions)) opFail();
+ if (isNotBol(msaOptions)) {
+ opFail();
+ }
return;
} else if (isNewLine(chars, sprev, end) && s != end) {
return;
@@ -626,13 +664,16 @@ class ByteCodeMachine extends StackMachine {
if (s == end) {
if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
if (str == end || !isNewLine(chars, sprev, end)) {
- if (isNotEol(msaOptions)) opFail();
+ if (isNotEol(msaOptions)) {
+ opFail();
+ }
}
return;
- } else {
- if (isNotEol(msaOptions)) opFail();
- return;
}
+ if (isNotEol(msaOptions)) {
+ opFail();
+ }
+ return;
} else if (isNewLine(chars, s, end)) {
return;
}
@@ -643,13 +684,16 @@ class ByteCodeMachine extends StackMachine {
if (s == end) {
if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
if (str == end || !isNewLine(chars, sprev, end)) {
- if (isNotEol(msaOptions)) opFail();
+ if (isNotEol(msaOptions)) {
+ opFail();
+ }
}
return;
- } else {
- if (isNotEol(msaOptions)) opFail();
- return;
}
+ if (isNotEol(msaOptions)) {
+ opFail();
+ }
+ return;
} else if (isNewLine(chars, s, end) && s + 1 == end) {
return;
}
@@ -657,40 +701,42 @@ class ByteCodeMachine extends StackMachine {
}
private void opBeginPosition() {
- if (s != msaStart) opFail();
+ if (s != msaStart) {
+ opFail();
+ }
}
private void opMemoryStartPush() {
- int mem = code[ip++];
+ final int mem = code[ip++];
pushMemStart(mem, s);
}
private void opMemoryStart() {
- int mem = code[ip++];
+ final int mem = code[ip++];
repeatStk[memStartStk + mem] = s;
}
private void opMemoryEndPush() {
- int mem = code[ip++];
+ final int mem = code[ip++];
pushMemEnd(mem, s);
}
private void opMemoryEnd() {
- int mem = code[ip++];
+ final int mem = code[ip++];
repeatStk[memEndStk + mem] = s;
}
private void opMemoryEndPushRec() {
- int mem = code[ip++];
- int stkp = getMemStart(mem); /* should be before push mem-end. */
+ final int mem = code[ip++];
+ final int stkp = getMemStart(mem); /* should be before push mem-end. */
pushMemEnd(mem, s);
repeatStk[memStartStk + mem] = stkp;
}
private void opMemoryEndRec() {
- int mem = code[ip++];
+ final int mem = code[ip++];
repeatStk[memEndStk + mem] = s;
- int stkp = getMemStart(mem);
+ final int stkp = getMemStart(mem);
if (BitStatus.bsAt(regex.btMemStart, mem)) {
repeatStk[memStartStk + mem] = stkp;
@@ -701,36 +747,40 @@ class ByteCodeMachine extends StackMachine {
pushMemEndMark(mem);
}
- private boolean backrefInvalid(int mem) {
+ private boolean backrefInvalid(final int mem) {
return repeatStk[memEndStk + mem] == INVALID_INDEX || repeatStk[memStartStk + mem] == INVALID_INDEX;
}
- private int backrefStart(int mem) {
+ private int backrefStart(final int mem) {
return bsAt(regex.btMemStart, mem) ? stack[repeatStk[memStartStk + mem]].getMemPStr() : repeatStk[memStartStk + mem];
}
- private int backrefEnd(int mem) {
+ private int backrefEnd(final int mem) {
return bsAt(regex.btMemEnd, mem) ? stack[repeatStk[memEndStk + mem]].getMemPStr() : repeatStk[memEndStk + mem];
}
- private void backref(int mem) {
+ private void backref(final int mem) {
/* if you want to remove following line,
you should check in parse and compile time. (numMem) */
if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;}
int pstart = backrefStart(mem);
- int pend = backrefEnd(mem);
+ final int pend = backrefEnd(mem);
int n = pend - pstart;
if (s + n > range) {opFail(); return;}
sprev = s;
// STRING_CMP
- while(n-- > 0) if (chars[pstart++] != chars[s++]) {opFail(); return;}
+ while(n-- > 0) {
+ if (chars[pstart++] != chars[s++]) {opFail(); return;}
+ }
// beyond string check
if (sprev < range) {
- while (sprev + 1 < s) sprev++;
+ while (sprev + 1 < s) {
+ sprev++;
+ }
}
}
@@ -747,15 +797,15 @@ class ByteCodeMachine extends StackMachine {
}
private void opBackRefNIC() {
- int mem = code[ip++];
+ final int mem = code[ip++];
/* if you want to remove following line,
you should check in parse and compile time. (numMem) */
if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;}
- int pstart = backrefStart(mem);
- int pend = backrefEnd(mem);
+ final int pstart = backrefStart(mem);
+ final int pend = backrefEnd(mem);
- int n = pend - pstart;
+ final int n = pend - pstart;
if (s + n > range) {opFail(); return;}
sprev = s;
@@ -764,19 +814,23 @@ class ByteCodeMachine extends StackMachine {
s = value;
// if (sprev < chars.length)
- while (sprev + 1 < s) sprev++;
+ while (sprev + 1 < s) {
+ sprev++;
+ }
}
private void opBackRefMulti() {
- int tlen = code[ip++];
+ final int tlen = code[ip++];
int i;
loop:for (i=0; i<tlen; i++) {
- int mem = code[ip++];
- if (backrefInvalid(mem)) continue;
+ final int mem = code[ip++];
+ if (backrefInvalid(mem)) {
+ continue;
+ }
int pstart = backrefStart(mem);
- int pend = backrefEnd(mem);
+ final int pend = backrefEnd(mem);
int n = pend - pstart;
if (s + n > range) {opFail(); return;}
@@ -785,14 +839,18 @@ class ByteCodeMachine extends StackMachine {
int swork = s;
while (n-- > 0) {
- if (chars[pstart++] != chars[swork++]) continue loop;
+ if (chars[pstart++] != chars[swork++]) {
+ continue loop;
+ }
}
s = swork;
// beyond string check
if (sprev < range) {
- while (sprev + 1 < s) sprev++;
+ while (sprev + 1 < s) {
+ sprev++;
+ }
}
ip += tlen - i - 1; // * SIZE_MEMNUM (1)
@@ -802,27 +860,34 @@ class ByteCodeMachine extends StackMachine {
}
private void opBackRefMultiIC() {
- int tlen = code[ip++];
+ final int tlen = code[ip++];
int i;
loop:for (i=0; i<tlen; i++) {
- int mem = code[ip++];
- if (backrefInvalid(mem)) continue;
+ final int mem = code[ip++];
+ if (backrefInvalid(mem)) {
+ continue;
+ }
- int pstart = backrefStart(mem);
- int pend = backrefEnd(mem);
+ final int pstart = backrefStart(mem);
+ final int pend = backrefEnd(mem);
- int n = pend - pstart;
+ final int n = pend - pstart;
if (s + n > range) {opFail(); return;}
sprev = s;
value = s;
- if (!stringCmpIC(regex.caseFoldFlag, pstart, this, n, end)) continue loop; // STRING_CMP_VALUE_IC
+ if (!stringCmpIC(regex.caseFoldFlag, pstart, this, n, end))
+ {
+ continue loop; // STRING_CMP_VALUE_IC
+ }
s = value;
// if (sprev < chars.length)
- while (sprev + 1 < s) sprev++;
+ while (sprev + 1 < s) {
+ sprev++;
+ }
ip += tlen - i - 1; // * SIZE_MEMNUM (1)
break; /* success */
@@ -830,23 +895,25 @@ class ByteCodeMachine extends StackMachine {
if (i == tlen) {opFail(); return;}
}
- private boolean memIsInMemp(int mem, int num, int memp) {
- for (int i=0; i<num; i++) {
- int m = code[memp++];
- if (mem == m) return true;
+ private boolean memIsInMemp(final int mem, final int num, final int mempp) {
+ for (int i=0, memp = mempp; i<num; i++) {
+ final int m = code[memp++];
+ if (mem == m) {
+ return true;
+ }
}
return false;
}
// USE_BACKREF_AT_LEVEL // (s) and (end) implicit
- private boolean backrefMatchAtNestedLevel(boolean ignoreCase, int caseFoldFlag,
- int nest, int memNum, int memp) {
+ private boolean backrefMatchAtNestedLevel(final boolean ignoreCase, final int caseFoldFlag,
+ final int nest, final int memNum, final int memp) {
int pend = -1;
int level = 0;
int k = stk - 1;
while (k >= 0) {
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if (e.type == CALL_FRAME) {
level--;
@@ -855,9 +922,11 @@ class ByteCodeMachine extends StackMachine {
} else if (level == nest) {
if (e.type == MEM_START) {
if (memIsInMemp(e.getMemNum(), memNum, memp)) {
- int pstart = e.getMemPStr();
+ final int pstart = e.getMemPStr();
if (pend != -1) {
- if (pend - pstart > end - s) return false; /* or goto next_mem; */
+ if (pend - pstart > end - s) {
+ return false; /* or goto next_mem; */
+ }
int p = pstart;
value = s;
@@ -867,7 +936,9 @@ class ByteCodeMachine extends StackMachine {
}
} else {
while (p < pend) {
- if (chars[p++] != chars[value++]) return false; /* or goto next_mem; */
+ if (chars[p++] != chars[value++]) {
+ return false; /* or goto next_mem; */
+ }
}
}
s = value;
@@ -887,32 +958,23 @@ class ByteCodeMachine extends StackMachine {
}
private void opBackRefAtLevel() {
- int ic = code[ip++];
- int level = code[ip++];
- int tlen = code[ip++];
+ final int ic = code[ip++];
+ final int level = code[ip++];
+ final int tlen = code[ip++];
sprev = s;
if (backrefMatchAtNestedLevel(ic != 0, regex.caseFoldFlag, level, tlen, ip)) { // (s) and (end) implicit
- while (sprev + 1 < s) sprev++;
+ while (sprev + 1 < s) {
+ sprev++;
+ }
ip += tlen; // * SIZE_MEMNUM
} else {
{opFail(); return;}
}
}
- /* no need: IS_DYNAMIC_OPTION() == 0 */
- private void opSetOptionPush() {
- // option = code[ip++]; // final for now
- pushAlt(ip, s, sprev);
- ip += OPSize.SET_OPTION + OPSize.FAIL;
- }
-
- private void opSetOption() {
- // option = code[ip++]; // final for now
- }
-
private void opNullCheckStart() {
- int mem = code[ip++];
+ final int mem = code[ip++];
pushNullCheckStart(mem, s);
}
@@ -936,8 +998,8 @@ class ByteCodeMachine extends StackMachine {
}
private void opNullCheckEnd() {
- int mem = code[ip++];
- int isNull = nullCheck(mem, s); /* mem: null check id */
+ final int mem = code[ip++];
+ final int isNull = nullCheck(mem, s); /* mem: null check id */
if (isNull != 0) {
if (Config.DEBUG_MATCH) {
@@ -950,8 +1012,8 @@ class ByteCodeMachine extends StackMachine {
// USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
private void opNullCheckEndMemST() {
- int mem = code[ip++]; /* mem: null check id */
- int isNull = nullCheckMemSt(mem, s);
+ final int mem = code[ip++]; /* mem: null check id */
+ final int isNull = nullCheckMemSt(mem, s);
if (isNull != 0) {
if (Config.DEBUG_MATCH) {
@@ -965,7 +1027,7 @@ class ByteCodeMachine extends StackMachine {
// USE_SUBEXP_CALL
private void opNullCheckEndMemSTPush() {
- int mem = code[ip++]; /* mem: null check id */
+ final int mem = code[ip++]; /* mem: null check id */
int isNull;
if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
@@ -991,7 +1053,7 @@ class ByteCodeMachine extends StackMachine {
}
private void opPush() {
- int addr = code[ip++];
+ final int addr = code[ip++];
pushAlt(ip + addr, s, sprev);
}
@@ -1000,7 +1062,7 @@ class ByteCodeMachine extends StackMachine {
}
private void opPushOrJumpExact1() {
- int addr = code[ip++];
+ final int addr = code[ip++];
// beyond string check
if (s < range && code[ip] == chars[s]) {
ip++;
@@ -1011,7 +1073,7 @@ class ByteCodeMachine extends StackMachine {
}
private void opPushIfPeekNext() {
- int addr = code[ip++];
+ final int addr = code[ip++];
// beyond string check
if (s < range && code[ip] == chars[s]) {
ip++;
@@ -1022,8 +1084,8 @@ class ByteCodeMachine extends StackMachine {
}
private void opRepeat() {
- int mem = code[ip++]; /* mem: OP_REPEAT ID */
- int addr= code[ip++];
+ final int mem = code[ip++]; /* mem: OP_REPEAT ID */
+ final int addr= code[ip++];
// ensure1();
repeatStk[mem] = stk;
@@ -1035,8 +1097,8 @@ class ByteCodeMachine extends StackMachine {
}
private void opRepeatNG() {
- int mem = code[ip++]; /* mem: OP_REPEAT ID */
- int addr= code[ip++];
+ final int mem = code[ip++]; /* mem: OP_REPEAT ID */
+ final int addr= code[ip++];
// ensure1();
repeatStk[mem] = stk;
@@ -1048,8 +1110,8 @@ class ByteCodeMachine extends StackMachine {
}
}
- private void repeatInc(int mem, int si) {
- StackEntry e = stack[si];
+ private void repeatInc(final int mem, final int si) {
+ final StackEntry e = stack[si];
e.increaseRepeatCount();
@@ -1065,25 +1127,25 @@ class ByteCodeMachine extends StackMachine {
}
private void opRepeatInc() {
- int mem = code[ip++]; /* mem: OP_REPEAT ID */
- int si = repeatStk[mem];
+ final int mem = code[ip++]; /* mem: OP_REPEAT ID */
+ final int si = repeatStk[mem];
repeatInc(mem, si);
}
private void opRepeatIncSG() {
- int mem = code[ip++]; /* mem: OP_REPEAT ID */
- int si = getRepeat(mem);
+ final int mem = code[ip++]; /* mem: OP_REPEAT ID */
+ final int si = getRepeat(mem);
repeatInc(mem, si);
}
- private void repeatIncNG(int mem, int si) {
- StackEntry e = stack[si];
+ private void repeatIncNG(final int mem, final int si) {
+ final StackEntry e = stack[si];
e.increaseRepeatCount();
if (e.getRepeatCount() < regex.repeatRangeHi[mem]) {
if (e.getRepeatCount() >= regex.repeatRangeLo[mem]) {
- int pcode = e.getRepeatPCode();
+ final int pcode = e.getRepeatPCode();
pushRepeatInc(si);
pushAlt(pcode, s, sprev);
} else {
@@ -1096,14 +1158,14 @@ class ByteCodeMachine extends StackMachine {
}
private void opRepeatIncNG() {
- int mem = code[ip++];
- int si = repeatStk[mem];
+ final int mem = code[ip++];
+ final int si = repeatStk[mem];
repeatIncNG(mem, si);
}
private void opRepeatIncNGSG() {
- int mem = code[ip++];
- int si = getRepeat(mem);
+ final int mem = code[ip++];
+ final int si = getRepeat(mem);
repeatIncNG(mem, si);
}
@@ -1112,13 +1174,13 @@ class ByteCodeMachine extends StackMachine {
}
private void opPopPos() {
- StackEntry e = stack[posEnd()];
+ final StackEntry e = stack[posEnd()];
s = e.getStatePStr();
sprev= e.getStatePStrPrev();
}
private void opPushPosNot() {
- int addr = code[ip++];
+ final int addr = code[ip++];
pushPosNot(ip + addr, s, sprev);
}
@@ -1136,23 +1198,16 @@ class ByteCodeMachine extends StackMachine {
}
private void opLookBehind() {
- int tlen = code[ip++];
+ final int tlen = code[ip++];
s = EncodingHelper.stepBack(str, s, tlen);
if (s == -1) {opFail(); return;}
sprev = EncodingHelper.prevCharHead(str, s);
}
- private void opLookBehindSb() {
- int tlen = code[ip++];
- s -= tlen;
- if (s < str) {opFail(); return;}
- sprev = s == str ? -1 : s - 1;
- }
-
private void opPushLookBehindNot() {
- int addr = code[ip++];
- int tlen = code[ip++];
- int q = EncodingHelper.stepBack(str, s, tlen);
+ final int addr = code[ip++];
+ final int tlen = code[ip++];
+ final int q = EncodingHelper.stepBack(str, s, tlen);
if (q == -1) {
/* too short case -> success. ex. /(?<!XXX)a/.match("a")
If you want to change to fail, replace following line. */
@@ -1177,7 +1232,7 @@ class ByteCodeMachine extends StackMachine {
}
- StackEntry e = pop();
+ final StackEntry e = pop();
ip = e.getStatePCode();
s = e.getStatePStr();
sprev = e.getStatePStrPrev();
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
index a01e414c..fc61ee80 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
@@ -214,7 +214,7 @@ class ByteCodePrinter {
Arguments.OPTION, /*OP_SET_OPTION*/
};
- public ByteCodePrinter(Regex regex) {
+ public ByteCodePrinter(final Regex regex) {
code = regex.code;
codeLength = regex.codeLength;
operands = regex.operands;
@@ -226,33 +226,35 @@ class ByteCodePrinter {
return compiledByteCodeListToString();
}
- private void pString(StringBuilder sb, int len, int s) {
+ private void pString(final StringBuilder sb, final int len, final int s) {
sb.append(":");
sb.append(new String(code, s, len));
}
- private void pLenString(StringBuilder sb, int len, int s) {
+ private void pLenString(final StringBuilder sb, final int len, final int s) {
sb.append(":").append(len).append(":");
sb.append(new String(code, s, len));
}
- private void pLenStringFromTemplate(StringBuilder sb, int len, char[] tm, int idx) {
+ private static void pLenStringFromTemplate(final StringBuilder sb, final int len, final char[] tm, final int idx) {
sb.append(":T:").append(len).append(":");
sb.append(tm, idx, len);
}
- public int compiledByteCodeToString(StringBuilder sb, int bp) {
+ public int compiledByteCodeToString(final StringBuilder sb, final int bptr) {
int len, n, mem, addr, scn, cod;
BitSet bs;
CClassNode cc;
int tm, idx;
+ int bp = bptr;
sb.append("[").append(OpCodeNames[code[bp]]);
- int argType = OpCodeArgTypes[code[bp]];
- int ip = bp;
+ final int argType = OpCodeArgTypes[code[bp]];
+ final int ip = bp;
if (argType != Arguments.SPECIAL) {
bp++;
switch (argType) {
+ default:
case Arguments.NON:
break;
@@ -410,16 +412,18 @@ class ByteCodePrinter {
for (int i=0; i<len; i++) {
mem = code[bp];
bp += OPSize.MEMNUM;
- if (i > 0) sb.append(", ");
+ if (i > 0) {
+ sb.append(", ");
+ }
sb.append(mem);
}
break;
case OPCode.BACKREF_WITH_LEVEL: {
- int option = code[bp];
+ final int option = code[bp];
bp += OPSize.OPTION;
sb.append(":").append(option);
- int level = code[bp];
+ final int level = code[bp];
bp += OPSize.LENGTH;
sb.append(":").append(level);
sb.append(" ");
@@ -428,7 +432,9 @@ class ByteCodePrinter {
for (int i=0; i<len; i++) {
mem = code[bp];
bp += OPSize.MEMNUM;
- if (i > 0) sb.append(", ");
+ if (i > 0) {
+ sb.append(", ");
+ }
sb.append(mem);
}
break;
@@ -491,17 +497,19 @@ class ByteCodePrinter {
}
private String compiledByteCodeListToString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("code length: ").append(codeLength).append("\n");
int ncode = 0;
int bp = 0;
- int end = codeLength;
+ final int end = codeLength;
while (bp < end) {
ncode++;
- if (bp > 0) sb.append(ncode % 5 == 0 ? "\n" : " ");
+ if (bp > 0) {
+ sb.append(ncode % 5 == 0 ? "\n" : " ");
+ }
bp = compiledByteCodeToString(sb, bp);
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java b/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
index 260be2ab..3436e122 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
@@ -22,6 +22,7 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;
+@SuppressWarnings("javadoc")
public final class CodeRangeBuffer implements Cloneable {
private static final int INIT_MULTI_BYTE_RANGE_SIZE = 5;
private static final int ALL_MULTI_BYTE_RANGE = 0x7fffffff;
@@ -36,13 +37,13 @@ public final class CodeRangeBuffer implements Cloneable {
}
// CodeRange.isInCodeRange
- public boolean isInCodeRange(int code) {
+ public boolean isInCodeRange(final int code) {
int low = 0;
- int n = p[0];
+ final int n = p[0];
int high = n;
while (low < high) {
- int x = (low + high) >> 1;
+ final int x = (low + high) >> 1;
if (code > p[(x << 1) + 2]) {
low = x + 1;
} else {
@@ -52,7 +53,7 @@ public final class CodeRangeBuffer implements Cloneable {
return low < n && code >= p[(low << 1) + 1];
}
- private CodeRangeBuffer(CodeRangeBuffer orig) {
+ private CodeRangeBuffer(final CodeRangeBuffer orig) {
p = new int[orig.p.length];
System.arraycopy(orig.p, 0, p, 0, p.length);
used = orig.used;
@@ -60,7 +61,7 @@ public final class CodeRangeBuffer implements Cloneable {
@Override
public String toString() {
- StringBuilder buf = new StringBuilder();
+ final StringBuilder buf = new StringBuilder();
buf.append("CodeRange");
buf.append("\n used: ").append(used);
buf.append("\n code point: ").append(p[0]);
@@ -68,54 +69,64 @@ public final class CodeRangeBuffer implements Cloneable {
for (int i=0; i<p[0]; i++) {
buf.append("[").append(rangeNumToString(p[i * 2 + 1])).append("..").append(rangeNumToString(p[i * 2 + 2])).append("]");
- if (i > 0 && i % 6 == 0) buf.append("\n ");
+ if (i > 0 && i % 6 == 0) {
+ buf.append("\n ");
+ }
}
return buf.toString();
}
- private static String rangeNumToString(int num){
+ private static String rangeNumToString(final int num){
return "0x" + Integer.toString(num, 16);
}
- public void expand(int low) {
+ public void expand(final int low) {
int length = p.length;
do { length <<= 1; } while (length < low);
- int[]tmp = new int[length];
+ final int[]tmp = new int[length];
System.arraycopy(p, 0, tmp, 0, used);
p = tmp;
}
- public void ensureSize(int size) {
+ public void ensureSize(final int size) {
int length = p.length;
while (length < size ) { length <<= 1; }
if (p.length != length) {
- int[]tmp = new int[length];
+ final int[]tmp = new int[length];
System.arraycopy(p, 0, tmp, 0, used);
p = tmp;
}
}
- private void moveRight(int from, int to, int n) {
- if (to + n > p.length) expand(to + n);
+ private void moveRight(final int from, final int to, final int n) {
+ if (to + n > p.length) {
+ expand(to + n);
+ }
System.arraycopy(p, from, p, to, n);
- if (to + n > used) used = to + n;
+ if (to + n > used) {
+ used = to + n;
+ }
}
- protected void moveLeft(int from, int to, int n) {
+ protected void moveLeft(final int from, final int to, final int n) {
System.arraycopy(p, from, p, to, n);
}
- private void moveLeftAndReduce(int from, int to) {
+ private void moveLeftAndReduce(final int from, final int to) {
System.arraycopy(p, from, p, to, used - from);
used -= from - to;
}
- public void writeCodePoint(int pos, int b) {
- int u = pos + 1;
- if (p.length < u) expand(u);
+ public void writeCodePoint(final int pos, final int b) {
+ final int u = pos + 1;
+ if (p.length < u) {
+ expand(u);
+ }
p[pos] = b;
- if (used < u) used = u;
+ if (used < u) {
+ used = u;
+ }
}
@Override
@@ -125,23 +136,28 @@ public final class CodeRangeBuffer implements Cloneable {
// ugly part: these methods should be made OO
// add_code_range_to_buf
- public static CodeRangeBuffer addCodeRangeToBuff(CodeRangeBuffer pbuf, int from, int to) {
+ public static CodeRangeBuffer addCodeRangeToBuff(final CodeRangeBuffer pbufp, final int fromp, final int top) {
+ int from = fromp, to = top;
+ CodeRangeBuffer pbuf = pbufp;
+
if (from > to) {
- int n = from;
+ final int n = from;
from = to;
to = n;
}
- if (pbuf == null) pbuf = new CodeRangeBuffer(); // move to CClassNode
+ if (pbuf == null) {
+ pbuf = new CodeRangeBuffer(); // move to CClassNode
+ }
- int[]p = pbuf.p;
+ final int[]p = pbuf.p;
int n = p[0];
int low = 0;
int bound = n;
while (low < bound) {
- int x = (low + bound) >>> 1;
+ final int x = (low + bound) >>> 1;
if (from > p[x * 2 + 2]) {
low = x + 1;
} else {
@@ -153,7 +169,7 @@ public final class CodeRangeBuffer implements Cloneable {
bound = n;
while (high < bound) {
- int x = (high + bound) >>> 1;
+ final int x = (high + bound) >>> 1;
if (to >= p[x * 2 + 1] - 1) {
high = x + 1;
} else {
@@ -161,19 +177,25 @@ public final class CodeRangeBuffer implements Cloneable {
}
}
- int incN = low + 1 - high;
+ final int incN = low + 1 - high;
- if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES);
+ if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) {
+ throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES);
+ }
if (incN != 1) {
- if (from > p[low * 2 + 1]) from = p[low * 2 + 1];
- if (to < p[(high - 1) * 2 + 2]) to = p[(high - 1) * 2 + 2];
+ if (from > p[low * 2 + 1]) {
+ from = p[low * 2 + 1];
+ }
+ if (to < p[(high - 1) * 2 + 2]) {
+ to = p[(high - 1) * 2 + 2];
+ }
}
if (incN != 0 && high < n) {
- int fromPos = 1 + high * 2;
- int toPos = 1 + (low + 1) * 2;
- int size = (n - high) * 2;
+ final int fromPos = 1 + high * 2;
+ final int toPos = 1 + (low + 1) * 2;
+ final int size = (n - high) * 2;
if (incN > 0) {
pbuf.moveRight(fromPos, toPos, size);
@@ -182,7 +204,7 @@ public final class CodeRangeBuffer implements Cloneable {
}
}
- int pos = 1 + low * 2;
+ final int pos = 1 + low * 2;
// pbuf.ensureSize(pos + 2);
pbuf.writeCodePoint(pos, from);
pbuf.writeCodePoint(pos + 1, to);
@@ -193,37 +215,40 @@ public final class CodeRangeBuffer implements Cloneable {
}
// add_code_range, be aware of it returning null!
- public static CodeRangeBuffer addCodeRange(CodeRangeBuffer pbuf, ScanEnvironment env, int from, int to) {
+ public static CodeRangeBuffer addCodeRange(final CodeRangeBuffer pbuf, final ScanEnvironment env, final int from, final int to) {
if (from > to) {
if (env.syntax.allowEmptyRangeInCC()) {
return pbuf;
- } else {
- throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
+ throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
return addCodeRangeToBuff(pbuf, from, to);
}
// SET_ALL_MULTI_BYTE_RANGE
- protected static CodeRangeBuffer setAllMultiByteRange(CodeRangeBuffer pbuf) {
+ protected static CodeRangeBuffer setAllMultiByteRange(final CodeRangeBuffer pbuf) {
return addCodeRangeToBuff(pbuf, EncodingHelper.mbcodeStartPosition(), ALL_MULTI_BYTE_RANGE);
}
// ADD_ALL_MULTI_BYTE_RANGE
- public static CodeRangeBuffer addAllMultiByteRange(CodeRangeBuffer pbuf) {
+ public static CodeRangeBuffer addAllMultiByteRange(final CodeRangeBuffer pbuf) {
return setAllMultiByteRange(pbuf);
}
// not_code_range_buf
- public static CodeRangeBuffer notCodeRangeBuff(CodeRangeBuffer bbuf) {
+ public static CodeRangeBuffer notCodeRangeBuff(final CodeRangeBuffer bbuf) {
CodeRangeBuffer pbuf = null;
- if (bbuf == null) return setAllMultiByteRange(pbuf);
+ if (bbuf == null) {
+ return setAllMultiByteRange(pbuf);
+ }
- int[]p = bbuf.p;
- int n = p[0];
+ final int[]p = bbuf.p;
+ final int n = p[0];
- if (n <= 0) return setAllMultiByteRange(pbuf);
+ if (n <= 0) {
+ return setAllMultiByteRange(pbuf);
+ }
int pre = EncodingHelper.mbcodeStartPosition();
@@ -235,18 +260,26 @@ public final class CodeRangeBuffer implements Cloneable {
if (pre <= from - 1) {
pbuf = addCodeRangeToBuff(pbuf, pre, from - 1);
}
- if (to == ALL_MULTI_BYTE_RANGE) break;
+ if (to == ALL_MULTI_BYTE_RANGE) {
+ break;
+ }
pre = to + 1;
}
- if (to < ALL_MULTI_BYTE_RANGE) pbuf = addCodeRangeToBuff(pbuf, to + 1, ALL_MULTI_BYTE_RANGE);
+ if (to < ALL_MULTI_BYTE_RANGE) {
+ pbuf = addCodeRangeToBuff(pbuf, to + 1, ALL_MULTI_BYTE_RANGE);
+ }
return pbuf;
}
// or_code_range_buf
- public static CodeRangeBuffer orCodeRangeBuff(CodeRangeBuffer bbuf1, boolean not1,
- CodeRangeBuffer bbuf2, boolean not2) {
+ public static CodeRangeBuffer orCodeRangeBuff(final CodeRangeBuffer bbuf1p, final boolean not1p,
+ final CodeRangeBuffer bbuf2p, final boolean not2p) {
CodeRangeBuffer pbuf = null;
+ CodeRangeBuffer bbuf1 = bbuf1p;
+ CodeRangeBuffer bbuf2 = bbuf2p;
+ boolean not1 = not1p;
+ boolean not2 = not2p;
if (bbuf1 == null && bbuf2 == null) {
if (not1 || not2) {
@@ -266,13 +299,11 @@ public final class CodeRangeBuffer implements Cloneable {
if (bbuf1 == null) {
if (not1) {
return setAllMultiByteRange(pbuf);
- } else {
- if (!not2) {
- return bbuf2.clone();
- } else {
- return notCodeRangeBuff(bbuf2);
- }
}
+ if (!not2) {
+ return bbuf2.clone();
+ }
+ return notCodeRangeBuff(bbuf2);
}
if (not1) {
@@ -289,12 +320,12 @@ public final class CodeRangeBuffer implements Cloneable {
pbuf = notCodeRangeBuff(bbuf2);
}
- int[]p1 = bbuf1.p;
- int n1 = p1[0];
+ final int[]p1 = bbuf1.p;
+ final int n1 = p1[0];
for (int i=0; i<n1; i++) {
- int from = p1[i * 2 + 1];
- int to = p1[i * 2 + 2];
+ final int from = p1[i * 2 + 1];
+ final int to = p1[i * 2 + 2];
pbuf = addCodeRangeToBuff(pbuf, from, to);
}
@@ -302,16 +333,18 @@ public final class CodeRangeBuffer implements Cloneable {
}
// and_code_range1
- public static CodeRangeBuffer andCodeRange1(CodeRangeBuffer pbuf, int from1, int to1, int[]data, int n) {
+ public static CodeRangeBuffer andCodeRange1(final CodeRangeBuffer pbufp, final int from1p, final int to1p, final int[]data, final int n) {
+ CodeRangeBuffer pbuf = pbufp;
+ int from1 = from1p, to1 = to1p;
+
for (int i=0; i<n; i++) {
- int from2 = data[i * 2 + 1];
- int to2 = data[i * 2 + 2];
+ final int from2 = data[i * 2 + 1];
+ final int to2 = data[i * 2 + 2];
if (from2 < from1) {
if (to2 < from1) {
continue;
- } else {
- from1 = to2 + 1;
}
+ from1 = to2 + 1;
} else if (from2 <= to1) {
if (to2 < to1) {
if (from1 <= from2 - 1) {
@@ -324,7 +357,9 @@ public final class CodeRangeBuffer implements Cloneable {
} else {
from1 = from2;
}
- if (from1 > to1) break;
+ if (from1 > to1) {
+ break;
+ }
}
if (from1 <= to1) {
@@ -335,15 +370,22 @@ public final class CodeRangeBuffer implements Cloneable {
}
// and_code_range_buf
- public static CodeRangeBuffer andCodeRangeBuff(CodeRangeBuffer bbuf1, boolean not1,
- CodeRangeBuffer bbuf2, boolean not2) {
+ public static CodeRangeBuffer andCodeRangeBuff(final CodeRangeBuffer bbuf1p, final boolean not1p,
+ final CodeRangeBuffer bbuf2p, final boolean not2p) {
CodeRangeBuffer pbuf = null;
+ CodeRangeBuffer bbuf1 = bbuf1p;
+ CodeRangeBuffer bbuf2 = bbuf2p;
+ boolean not1 = not1p, not2 = not2p;
if (bbuf1 == null) {
- if (not1 && bbuf2 != null) return bbuf2.clone(); /* not1 != 0 -> not2 == 0 */
+ if (not1 && bbuf2 != null) {
+ return bbuf2.clone(); /* not1 != 0 -> not2 == 0 */
+ }
return null;
} else if (bbuf2 == null) {
- if (not2) return bbuf1.clone();
+ if (not2) {
+ return bbuf1.clone();
+ }
return null;
}
@@ -355,31 +397,35 @@ public final class CodeRangeBuffer implements Cloneable {
tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf;
}
- int[]p1 = bbuf1.p;
- int n1 = p1[0];
- int[]p2 = bbuf2.p;
- int n2 = p2[0];
+ final int[]p1 = bbuf1.p;
+ final int n1 = p1[0];
+ final int[]p2 = bbuf2.p;
+ final int n2 = p2[0];
if (!not2 && !not1) { /* 1 AND 2 */
for (int i=0; i<n1; i++) {
- int from1 = p1[i * 2 + 1];
- int to1 = p1[i * 2 + 2];
+ final int from1 = p1[i * 2 + 1];
+ final int to1 = p1[i * 2 + 2];
for (int j=0; j<n2; j++) {
- int from2 = p2[j * 2 + 1];
- int to2 = p2[j * 2 + 2];
+ final int from2 = p2[j * 2 + 1];
+ final int to2 = p2[j * 2 + 2];
- if (from2 > to1) break;
- if (to2 < from1) continue;
- int from = from1 > from2 ? from1 : from2;
- int to = to1 < to2 ? to1 : to2;
+ if (from2 > to1) {
+ break;
+ }
+ if (to2 < from1) {
+ continue;
+ }
+ final int from = from1 > from2 ? from1 : from2;
+ final int to = to1 < to2 ? to1 : to2;
pbuf = addCodeRangeToBuff(pbuf, from, to);
}
}
} else if (!not1) { /* 1 AND (not 2) */
for (int i=0; i<n1; i++) {
- int from1 = p1[i * 2 + 1];
- int to1 = p1[i * 2 + 2];
+ final int from1 = p1[i * 2 + 1];
+ final int to1 = p1[i * 2 + 2];
pbuf = andCodeRange1(pbuf, from1, to1, p2, n2);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
index c3356add..73752caa 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
@@ -36,7 +36,7 @@ abstract class Compiler implements ErrorMessages {
protected final Analyser analyser;
protected final Regex regex;
- protected Compiler(Analyser analyser) {
+ protected Compiler(final Analyser analyser) {
this.analyser = analyser;
this.regex = analyser.regex;
}
@@ -52,21 +52,25 @@ abstract class Compiler implements ErrorMessages {
protected abstract void compileAltNode(ConsAltNode node);
- private void compileStringRawNode(StringNode sn) {
- if (sn.length() <= 0) return;
+ private void compileStringRawNode(final StringNode sn) {
+ if (sn.length() <= 0) {
+ return;
+ }
addCompileString(sn.chars, sn.p, sn.length(), false);
}
- private void compileStringNode(StringNode node) {
- StringNode sn = node;
- if (sn.length() <= 0) return;
+ private void compileStringNode(final StringNode node) {
+ final StringNode sn = node;
+ if (sn.length() <= 0) {
+ return;
+ }
- boolean ambig = sn.isAmbig();
+ final boolean ambig = sn.isAmbig();
int p, prev;
p = prev = sn.p;
- int end = sn.end;
- char[] chars = sn.chars;
+ final int end = sn.end;
+ final char[] chars = sn.chars;
p++;
int slen = 1;
@@ -87,7 +91,7 @@ abstract class Compiler implements ErrorMessages {
protected abstract void compileEncloseNode(EncloseNode node);
protected abstract void compileAnchorNode(AnchorNode node);
- protected final void compileTree(Node node) {
+ protected final void compileTree(final Node node) {
switch (node.getType()) {
case NodeType.LIST:
ConsAltNode lin = (ConsAltNode)node;
@@ -101,7 +105,7 @@ abstract class Compiler implements ErrorMessages {
break;
case NodeType.STR:
- StringNode sn = (StringNode)node;
+ final StringNode sn = (StringNode)node;
if (sn.isRaw()) {
compileStringRawNode(sn);
} else {
@@ -126,7 +130,7 @@ abstract class Compiler implements ErrorMessages {
break;
case NodeType.ENCLOSE:
- EncloseNode enode = (EncloseNode)node;
+ final EncloseNode enode = (EncloseNode)node;
if (enode.isOption()) {
compileOptionNode(enode);
} else {
@@ -144,15 +148,17 @@ abstract class Compiler implements ErrorMessages {
} // switch
}
- protected final void compileTreeNTimes(Node node, int n) {
- for (int i=0; i<n; i++) compileTree(node);
+ protected final void compileTreeNTimes(final Node node, final int n) {
+ for (int i=0; i<n; i++) {
+ compileTree(node);
+ }
}
- protected void newSyntaxException(String message) {
+ protected void newSyntaxException(final String message) {
throw new SyntaxException(message);
}
- protected void newInternalException(String message) {
+ protected void newInternalException(final String message) {
throw new InternalException(message);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
index 79b5f73a..e55947c3 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
@@ -21,6 +21,7 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import java.io.PrintStream;
+@SuppressWarnings("javadoc")
public interface Config {
final int CHAR_TABLE_SIZE = 256;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
index 0c9c8ab4..af2d9a6b 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
@@ -19,11 +19,11 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+import java.util.Arrays;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
-import java.util.Arrays;
-
+@SuppressWarnings("javadoc")
public final class EncodingHelper {
final static int NEW_LINE = 0x000a;
@@ -34,19 +34,19 @@ public final class EncodingHelper {
final static char[] EMPTYCHARS = new char[0];
final static int[][] codeRanges = new int[15][];
- public static int digitVal(int code) {
+ public static int digitVal(final int code) {
return code - '0';
}
- public static int odigitVal(int code) {
+ public static int odigitVal(final int code) {
return digitVal(code);
}
- public static boolean isXDigit(int code) {
+ public static boolean isXDigit(final int code) {
return Character.isDigit(code) || (code >= 'a' && code <= 'f') || (code >= 'A' && code <= 'F');
}
- public static int xdigitVal(int code) {
+ public static int xdigitVal(final int code) {
if (Character.isDigit(code)) {
return code - '0';
} else if (code >= 'a' && code <= 'f') {
@@ -56,38 +56,43 @@ public final class EncodingHelper {
}
}
- public static boolean isDigit(int code) {
+ public static boolean isDigit(final int code) {
return code >= '0' && code <= '9';
}
- public static boolean isWord(int code) {
+ public static boolean isWord(final int code) {
// letter, digit, or '_'
return (1 << Character.getType(code) & CharacterType.WORD_MASK) != 0;
}
- public static boolean isNewLine(int code) {
+ public static boolean isNewLine(final int code) {
return code == NEW_LINE || code == RETURN || code == LINE_SEPARATOR || code == PARAGRAPH_SEPARATOR;
}
- public static boolean isNewLine(char[] chars, int p, int end) {
+ public static boolean isNewLine(final char[] chars, final int p, final int end) {
return p < end && isNewLine(chars[p]);
}
// Encoding.prevCharHead
- public static int prevCharHead(int p, int s) {
+ public static int prevCharHead(final int p, final int s) {
return s <= p ? -1 : s - 1;
}
/* onigenc_get_right_adjust_char_head_with_prev */
- public static int rightAdjustCharHeadWithPrev(int s, IntHolder prev) {
- if (prev != null) prev.value = -1; /* Sorry */
+ public static int rightAdjustCharHeadWithPrev(final int s, final IntHolder prev) {
+ if (prev != null) {
+ prev.value = -1; /* Sorry */
+ }
return s;
}
// Encoding.stepBack
- public static int stepBack(int p, int s, int n) {
- while (s != -1 && n-- > 0) {
- if (s <= p) return -1;
+ public static int stepBack(final int p, final int sp, final int np) {
+ int s = sp, n = np;
+ while (s != -1 && n-- > 0) {
+ if (s <= p) {
+ return -1;
+ }
s--;
}
return s;
@@ -97,7 +102,7 @@ public final class EncodingHelper {
return 0x80;
}
- public static char[] caseFoldCodesByString(int flag, char c) {
+ public static char[] caseFoldCodesByString(final int flag, final char c) {
char[] codes = EMPTYCHARS;
final char upper = toUpperCase(c);
@@ -117,13 +122,13 @@ public final class EncodingHelper {
return codes;
}
- public static void applyAllCaseFold(int flag, ApplyCaseFold fun, Object arg) {
+ public static void applyAllCaseFold(final int flag, final ApplyCaseFold fun, final Object arg) {
for (int c = 0; c < 0xffff; c++) {
if (Character.isLowerCase(c)) {
final int upper = toUpperCase(c);
if (upper != c) {
- fun.apply(c, upper, arg);
+ ApplyCaseFold.apply(c, upper, arg);
}
}
}
@@ -134,40 +139,40 @@ public final class EncodingHelper {
final int upper = toUpperCase(c);
if (upper != c) {
- fun.apply(upper, c, arg);
+ ApplyCaseFold.apply(upper, c, arg);
}
}
}
}
- public static char toLowerCase(char c) {
+ public static char toLowerCase(final char c) {
return (char)toLowerCase((int)c);
}
- public static int toLowerCase(int c) {
+ public static int toLowerCase(final int c) {
if (c < 128) {
return ('A' <= c && c <= 'Z') ? (c + ('a' - 'A')) : c;
}
// Do not convert non-ASCII upper case character to ASCII lower case.
- int lower = Character.toLowerCase(c);
+ final int lower = Character.toLowerCase(c);
return (lower < 128) ? c : lower;
}
- public static char toUpperCase(char c) {
+ public static char toUpperCase(final char c) {
return (char)toUpperCase((int)c);
}
- public static int toUpperCase(int c) {
+ public static int toUpperCase(final int c) {
if (c < 128) {
return ('a' <= c && c <= 'z') ? c + ('A' - 'a') : c;
}
// Do not convert non-ASCII lower case character to ASCII upper case.
- int upper = Character.toUpperCase(c);
+ final int upper = Character.toUpperCase(c);
return (upper < 128) ? c : upper;
}
- public static int[] ctypeCodeRange(int ctype, IntHolder sbOut) {
+ public static int[] ctypeCodeRange(final int ctype, final IntHolder sbOut) {
sbOut.value = 0x100; // use bitset for codes smaller than 256
int[] range = null;
@@ -206,13 +211,13 @@ public final class EncodingHelper {
}
// CodeRange.isInCodeRange
- public static boolean isInCodeRange(int[] p, int offset, int code) {
+ public static boolean isInCodeRange(final int[] p, final int offset, final int code) {
int low = 0;
- int n = p[offset];
+ final int n = p[offset];
int high = n ;
while (low < high) {
- int x = (low + high) >> 1;
+ final int x = (low + high) >> 1;
if (code > p[(x << 1) + 2 + offset]) {
low = x + 1;
} else {
@@ -225,7 +230,7 @@ public final class EncodingHelper {
/**
* @see <a href="http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt">http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt</a>
*/
- public static boolean isCodeCType(int code, int ctype) {
+ public static boolean isCodeCType(final int code, final int ctype) {
int type;
switch (ctype) {
case CharacterType.NEWLINE:
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
index c4dcac28..27c010e8 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
@@ -21,7 +21,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isSingleline;
import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar;
@@ -36,7 +35,7 @@ class Lexer extends ScannerSupport {
protected final Syntax syntax; // fast access to syntax
protected final Token token = new Token(); // current token
- protected Lexer(ScanEnvironment env, char[] chars, int p, int end) {
+ protected Lexer(final ScanEnvironment env, final char[] chars, final int p, final int end) {
super(chars, p, end);
this.env = env;
this.syntax = env.syntax;
@@ -48,14 +47,13 @@ class Lexer extends ScannerSupport {
*/
private int fetchRangeQuantifier() {
mark();
- boolean synAllow = syntax.allowInvalidInterval();
+ final boolean synAllow = syntax.allowInvalidInterval();
if (!left()) {
if (synAllow) {
return 1; /* "....{" : OK! */
- } else {
- throw new SyntaxException(ERR_END_PATTERN_AT_LEFT_BRACE);
}
+ throw new SyntaxException(ERR_END_PATTERN_AT_LEFT_BRACE);
}
if (!synAllow) {
@@ -83,13 +81,15 @@ class Lexer extends ScannerSupport {
}
}
- if (!left()) return invalidRangeQuantifier(synAllow);
+ if (!left()) {
+ return invalidRangeQuantifier(synAllow);
+ }
fetch();
int up;
int ret = 0;
if (c == ',') {
- int prev = p; // ??? last
+ final int prev = p; // ??? last
up = scanUnsignedNumber();
if (up < 0) {
throw new ValueException(ERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE);
@@ -99,25 +99,35 @@ class Lexer extends ScannerSupport {
}
if (p == prev) {
- if (nonLow) return invalidRangeQuantifier(synAllow);
+ if (nonLow) {
+ return invalidRangeQuantifier(synAllow);
+ }
up = QuantifierNode.REPEAT_INFINITE; /* {n,} : {n,infinite} */
}
} else {
- if (nonLow) return invalidRangeQuantifier(synAllow);
+ if (nonLow) {
+ return invalidRangeQuantifier(synAllow);
+ }
unfetch();
up = low; /* {n} : exact n times */
ret = 2; /* fixed */
}
- if (!left()) return invalidRangeQuantifier(synAllow);
+ if (!left()) {
+ return invalidRangeQuantifier(synAllow);
+ }
fetch();
if (syntax.opEscBraceInterval()) {
- if (c != syntax.metaCharTable.esc) return invalidRangeQuantifier(synAllow);
+ if (c != syntax.metaCharTable.esc) {
+ return invalidRangeQuantifier(synAllow);
+ }
fetch();
}
- if (c != '}') return invalidRangeQuantifier(synAllow);
+ if (c != '}') {
+ return invalidRangeQuantifier(synAllow);
+ }
if (!isRepeatInfinite(up) && low > up) {
throw new ValueException(ERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE);
@@ -130,13 +140,12 @@ class Lexer extends ScannerSupport {
return ret; /* 0: normal {n,m}, 2: fixed {n} */
}
- private int invalidRangeQuantifier(boolean synAllow) {
+ private int invalidRangeQuantifier(final boolean synAllow) {
if (synAllow) {
restore();
return 1;
- } else {
- throw new SyntaxException(ERR_INVALID_REPEAT_RANGE_PATTERN);
}
+ throw new SyntaxException(ERR_INVALID_REPEAT_RANGE_PATTERN);
}
@SuppressWarnings("fallthrough")
@@ -218,35 +227,26 @@ class Lexer extends ScannerSupport {
}
}
- private int nameEndCodePoint(int start) {
- switch(start) {
- case '<':
- return '>';
- case '\'':
- return '\'';
- default:
- return 0;
- }
- }
-
- private void fetchTokenInCCFor_charType(boolean flag, int type) {
+ private void fetchTokenInCCFor_charType(final boolean flag, final int type) {
token.type = TokenType.CHAR_TYPE;
token.setPropCType(type);
token.setPropNot(flag);
}
private void fetchTokenInCCFor_x() {
- if (!left()) return;
- int last = p;
+ if (!left()) {
+ return;
+ }
+ final int last = p;
if (peekIs('{') && syntax.opEscXBraceHex8()) {
inc();
- int num = scanUnsignedHexadecimalNumber(8);
+ final int num = scanUnsignedHexadecimalNumber(8);
if (num < 0) {
throw new ValueException(ERR_TOO_BIG_WIDE_CHAR_VALUE);
}
if (left()) {
- int c2 = peek();
+ final int c2 = peek();
if (EncodingHelper.isXDigit(c2)) {
throw new ValueException(ERR_TOO_LONG_WIDE_CHAR_VALUE);
}
@@ -274,8 +274,10 @@ class Lexer extends ScannerSupport {
}
private void fetchTokenInCCFor_u() {
- if (!left()) return;
- int last = p;
+ if (!left()) {
+ return;
+ }
+ final int last = p;
if (syntax.op2EscUHex4()) {
int num = scanUnsignedHexadecimalNumber(4);
@@ -293,7 +295,7 @@ class Lexer extends ScannerSupport {
private void fetchTokenInCCFor_digit() {
if (syntax.opEscOctal3()) {
unfetch();
- int last = p;
+ final int last = p;
int num = scanUnsignedOctalNumber(3);
if (num < 0) {
throw new ValueException(ERR_TOO_BIG_NUMBER);
@@ -329,7 +331,9 @@ class Lexer extends ScannerSupport {
} else if (c == '-') {
token.type = TokenType.CC_RANGE;
} else if (c == syntax.metaCharTable.esc) {
- if (!syntax.backSlashEscapeInCC()) return token.type;
+ if (!syntax.backSlashEscapeInCC()) {
+ return token.type;
+ }
if (!left()) {
throw new SyntaxException(ERR_END_PATTERN_AT_ESCAPE);
}
@@ -357,10 +361,14 @@ class Lexer extends ScannerSupport {
fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE);
break;
case 'h':
- if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(false, CharacterType.XDIGIT);
+ if (syntax.op2EscHXDigit()) {
+ fetchTokenInCCFor_charType(false, CharacterType.XDIGIT);
+ }
break;
case 'H':
- if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
+ if (syntax.op2EscHXDigit()) {
+ fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
+ }
break;
case 'x':
fetchTokenInCCFor_x();
@@ -381,7 +389,7 @@ class Lexer extends ScannerSupport {
default:
unfetch();
- int num = fetchEscapedValue();
+ final int num = fetchEscapedValue();
if (token.getC() != num) {
token.setCode(num);
token.type = TokenType.CODE_POINT;
@@ -395,7 +403,7 @@ class Lexer extends ScannerSupport {
return token.type;
}
- private void fetchTokenFor_repeat(int lower, int upper) {
+ private void fetchTokenFor_repeat(final int lower, final int upper) {
token.type = TokenType.OP_REPEAT;
token.setRepeatLower(lower);
token.setRepeatUpper(upper);
@@ -418,18 +426,20 @@ class Lexer extends ScannerSupport {
} // inner switch
}
- private void fetchTokenFor_anchor(int subType) {
+ private void fetchTokenFor_anchor(final int subType) {
token.type = TokenType.ANCHOR;
token.setAnchor(subType);
}
private void fetchTokenFor_xBrace() {
- if (!left()) return;
+ if (!left()) {
+ return;
+ }
- int last = p;
+ final int last = p;
if (peekIs('{') && syntax.opEscXBraceHex8()) {
inc();
- int num = scanUnsignedHexadecimalNumber(8);
+ final int num = scanUnsignedHexadecimalNumber(8);
if (num < 0) {
throw new ValueException(ERR_TOO_BIG_WIDE_CHAR_VALUE);
}
@@ -461,8 +471,10 @@ class Lexer extends ScannerSupport {
}
private void fetchTokenFor_uHex() {
- if (!left()) return;
- int last = p;
+ if (!left()) {
+ return;
+ }
+ final int last = p;
if (syntax.op2EscUHex4()) {
int num = scanUnsignedHexadecimalNumber(4);
@@ -479,8 +491,8 @@ class Lexer extends ScannerSupport {
private void fetchTokenFor_digit() {
unfetch();
- int last = p;
- int num = scanUnsignedNumber();
+ final int last = p;
+ final int num = scanUnsignedNumber();
if (num < 0 || num > Config.MAX_BACKREF_NUM) { // goto skip_backref
} else if (syntax.opDecimalBackref() && (num <= env.numMem || num <= 9)) { /* This spec. from GNU regex */
if (syntax.strictCheckBackref()) {
@@ -505,7 +517,7 @@ class Lexer extends ScannerSupport {
private void fetchTokenFor_zero() {
if (syntax.opEscOctal3()) {
- int last = p;
+ final int last = p;
int num = scanUnsignedOctalNumber(c == '0' ? 2 : 3);
if (num < 0) {
throw new ValueException(ERR_TOO_BIG_NUMBER);
@@ -562,79 +574,129 @@ class Lexer extends ScannerSupport {
switch(c) {
case '*':
- if (syntax.opEscAsteriskZeroInf()) fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE);
+ if (syntax.opEscAsteriskZeroInf()) {
+ fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE);
+ }
break;
case '+':
- if (syntax.opEscPlusOneInf()) fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE);
+ if (syntax.opEscPlusOneInf()) {
+ fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE);
+ }
break;
case '?':
- if (syntax.opEscQMarkZeroOne()) fetchTokenFor_repeat(0, 1);
+ if (syntax.opEscQMarkZeroOne()) {
+ fetchTokenFor_repeat(0, 1);
+ }
break;
case '{':
- if (syntax.opEscBraceInterval()) fetchTokenFor_openBrace();
+ if (syntax.opEscBraceInterval()) {
+ fetchTokenFor_openBrace();
+ }
break;
case '|':
- if (syntax.opEscVBarAlt()) token.type = TokenType.ALT;
+ if (syntax.opEscVBarAlt()) {
+ token.type = TokenType.ALT;
+ }
break;
case '(':
- if (syntax.opEscLParenSubexp()) token.type = TokenType.SUBEXP_OPEN;
+ if (syntax.opEscLParenSubexp()) {
+ token.type = TokenType.SUBEXP_OPEN;
+ }
break;
case ')':
- if (syntax.opEscLParenSubexp()) token.type = TokenType.SUBEXP_CLOSE;
+ if (syntax.opEscLParenSubexp()) {
+ token.type = TokenType.SUBEXP_CLOSE;
+ }
break;
case 'w':
- if (syntax.opEscWWord()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD);
+ if (syntax.opEscWWord()) {
+ fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD);
+ }
break;
case 'W':
- if (syntax.opEscWWord()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD);
+ if (syntax.opEscWWord()) {
+ fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD);
+ }
break;
case 'b':
- if (syntax.opEscBWordBound()) fetchTokenFor_anchor(AnchorType.WORD_BOUND);
+ if (syntax.opEscBWordBound()) {
+ fetchTokenFor_anchor(AnchorType.WORD_BOUND);
+ }
break;
case 'B':
- if (syntax.opEscBWordBound()) fetchTokenFor_anchor(AnchorType.NOT_WORD_BOUND);
+ if (syntax.opEscBWordBound()) {
+ fetchTokenFor_anchor(AnchorType.NOT_WORD_BOUND);
+ }
break;
case '<':
- if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) fetchTokenFor_anchor(AnchorType.WORD_BEGIN);
+ if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) {
+ fetchTokenFor_anchor(AnchorType.WORD_BEGIN);
+ }
break;
case '>':
- if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) fetchTokenFor_anchor(AnchorType.WORD_END);
+ if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) {
+ fetchTokenFor_anchor(AnchorType.WORD_END);
+ }
break;
case 's':
- if (syntax.opEscSWhiteSpace()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE);
+ if (syntax.opEscSWhiteSpace()) {
+ fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE);
+ }
break;
case 'S':
- if (syntax.opEscSWhiteSpace()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE);
+ if (syntax.opEscSWhiteSpace()) {
+ fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE);
+ }
break;
case 'd':
- if (syntax.opEscDDigit()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT);
+ if (syntax.opEscDDigit()) {
+ fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT);
+ }
break;
case 'D':
- if (syntax.opEscDDigit()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT);
+ if (syntax.opEscDDigit()) {
+ fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT);
+ }
break;
case 'h':
- if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(false, CharacterType.XDIGIT);
+ if (syntax.op2EscHXDigit()) {
+ fetchTokenInCCFor_charType(false, CharacterType.XDIGIT);
+ }
break;
case 'H':
- if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
+ if (syntax.op2EscHXDigit()) {
+ fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
+ }
break;
case 'A':
- if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_BUF);
+ if (syntax.opEscAZBufAnchor()) {
+ fetchTokenFor_anchor(AnchorType.BEGIN_BUF);
+ }
break;
case 'Z':
- if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.SEMI_END_BUF);
+ if (syntax.opEscAZBufAnchor()) {
+ fetchTokenFor_anchor(AnchorType.SEMI_END_BUF);
+ }
break;
case 'z':
- if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.END_BUF);
+ if (syntax.opEscAZBufAnchor()) {
+ fetchTokenFor_anchor(AnchorType.END_BUF);
+ }
break;
case 'G':
- if (syntax.opEscCapitalGBeginAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_POSITION);
+ if (syntax.opEscCapitalGBeginAnchor()) {
+ fetchTokenFor_anchor(AnchorType.BEGIN_POSITION);
+ }
break;
case '`':
- if (syntax.op2EscGnuBufAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_BUF);
+ if (syntax.op2EscGnuBufAnchor()) {
+ fetchTokenFor_anchor(AnchorType.BEGIN_BUF);
+ }
break;
case '\'':
- if (syntax.op2EscGnuBufAnchor()) fetchTokenFor_anchor(AnchorType.END_BUF);
+ if (syntax.op2EscGnuBufAnchor()) {
+ fetchTokenFor_anchor(AnchorType.END_BUF);
+ }
break;
case 'x':
fetchTokenFor_xBrace();
@@ -659,7 +721,7 @@ class Lexer extends ScannerSupport {
default:
unfetch();
- int num = fetchEscapedValue();
+ final int num = fetchEscapedValue();
/* set_raw: */
if (token.getC() != num) {
@@ -684,22 +746,34 @@ class Lexer extends ScannerSupport {
{
switch(c) {
case '.':
- if (syntax.opDotAnyChar()) token.type = TokenType.ANYCHAR;
+ if (syntax.opDotAnyChar()) {
+ token.type = TokenType.ANYCHAR;
+ }
break;
case '*':
- if (syntax.opAsteriskZeroInf()) fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE);
+ if (syntax.opAsteriskZeroInf()) {
+ fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE);
+ }
break;
case '+':
- if (syntax.opPlusOneInf()) fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE);
+ if (syntax.opPlusOneInf()) {
+ fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE);
+ }
break;
case '?':
- if (syntax.opQMarkZeroOne()) fetchTokenFor_repeat(0, 1);
+ if (syntax.opQMarkZeroOne()) {
+ fetchTokenFor_repeat(0, 1);
+ }
break;
case '{':
- if (syntax.opBraceInterval()) fetchTokenFor_openBrace();
+ if (syntax.opBraceInterval()) {
+ fetchTokenFor_openBrace();
+ }
break;
case '|':
- if (syntax.opVBarAlt()) token.type = TokenType.ALT;
+ if (syntax.opVBarAlt()) {
+ token.type = TokenType.ALT;
+ }
break;
case '(':
@@ -713,9 +787,13 @@ class Lexer extends ScannerSupport {
}
fetch();
if (c == syntax.metaCharTable.esc) {
- if (left()) fetch();
+ if (left()) {
+ fetch();
+ }
} else {
- if (c == ')') break;
+ if (c == ')') {
+ break;
+ }
}
}
continue start; // goto start
@@ -723,19 +801,29 @@ class Lexer extends ScannerSupport {
unfetch();
}
- if (syntax.opLParenSubexp()) token.type = TokenType.SUBEXP_OPEN;
+ if (syntax.opLParenSubexp()) {
+ token.type = TokenType.SUBEXP_OPEN;
+ }
break;
case ')':
- if (syntax.opLParenSubexp()) token.type = TokenType.SUBEXP_CLOSE;
+ if (syntax.opLParenSubexp()) {
+ token.type = TokenType.SUBEXP_CLOSE;
+ }
break;
case '^':
- if (syntax.opLineAnchor()) fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.BEGIN_BUF : AnchorType.BEGIN_LINE);
+ if (syntax.opLineAnchor()) {
+ fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.BEGIN_BUF : AnchorType.BEGIN_LINE);
+ }
break;
case '$':
- if (syntax.opLineAnchor()) fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.END_BUF : AnchorType.END_LINE);
+ if (syntax.opLineAnchor()) {
+ fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.END_BUF : AnchorType.END_LINE);
+ }
break;
case '[':
- if (syntax.opBracketCC()) token.type = TokenType.CC_CC_OPEN;
+ if (syntax.opBracketCC()) {
+ token.type = TokenType.CC_CC_OPEN;
+ }
break;
case ']':
//if (*src > env->pattern) /* /].../ is allowed. */
@@ -745,7 +833,9 @@ class Lexer extends ScannerSupport {
if (Option.isExtend(env.option)) {
while (left()) {
fetch();
- if (EncodingHelper.isNewLine(c)) break;
+ if (EncodingHelper.isNewLine(c)) {
+ break;
+ }
}
continue start; // goto start
}
@@ -756,7 +846,10 @@ class Lexer extends ScannerSupport {
case '\n':
case '\r':
case '\f':
- if (Option.isExtend(env.option)) continue start; // goto start
+ if (Option.isExtend(env.option))
+ {
+ continue start; // goto start
+ }
break;
default: // string
@@ -798,11 +891,11 @@ class Lexer extends ScannerSupport {
}
}
- protected final void syntaxWarn(String message, char c) {
- syntaxWarn(message.replace("<%n>", Character.toString(c)));
+ protected final void syntaxWarn(final String message, final char ch) {
+ syntaxWarn(message.replace("<%n>", Character.toString(ch)));
}
- protected final void syntaxWarn(String message) {
+ protected final void syntaxWarn(final String message) {
if (Config.USE_WARN) {
env.reg.warnings.warn(message + ": /" + new String(chars, getBegin(), getEnd()) + "/");
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
index 76058737..b1a733d9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
@@ -21,10 +21,10 @@
package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindLongest;
-
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
+@SuppressWarnings("javadoc")
public abstract class Matcher extends IntHolder {
protected final Regex regex;
@@ -41,11 +41,11 @@ public abstract class Matcher extends IntHolder {
protected int msaBegin;
protected int msaEnd;
- public Matcher(Regex regex, char[] chars) {
+ public Matcher(final Regex regex, final char[] chars) {
this(regex, chars, 0, chars.length);
}
- public Matcher(Regex regex, char[] chars, int p, int end) {
+ public Matcher(final Regex regex, final char[] chars, final int p, final int end) {
this.regex = regex;
this.chars = chars;
@@ -70,33 +70,34 @@ public abstract class Matcher extends IntHolder {
return msaEnd;
}
- protected final void msaInit(int option, int start) {
+ protected final void msaInit(final int option, final int start) {
msaOptions = option;
msaStart = start;
- if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) msaBestLen = -1;
+ if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
+ msaBestLen = -1;
+ }
}
- public final int match(int at, int range, int option) {
+ public final int match(final int at, final int range, final int option) {
msaInit(option, at);
- int prev = EncodingHelper.prevCharHead(str, at);
+ final int prev = EncodingHelper.prevCharHead(str, at);
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
return matchAt(end /*range*/, at, prev);
- } else {
- return matchAt(range /*range*/, at, prev);
}
+ return matchAt(range /*range*/, at, prev);
}
int low, high; // these are the return values
- private boolean forwardSearchRange(char[] chars, int str, int end, int s, int range, IntHolder lowPrev) {
+ private boolean forwardSearchRange(final char[] ch, final int string, final int e, final int s, final int range, final IntHolder lowPrev) {
int pprev = -1;
int p = s;
if (Config.DEBUG_SEARCH) {
Config.log.println("forward_search_range: "+
- "str: " + str +
- ", end: " + end +
+ "str: " + string +
+ ", end: " + e +
", s: " + s +
", range: " + range);
}
@@ -106,7 +107,7 @@ public abstract class Matcher extends IntHolder {
}
retry:while (true) {
- p = regex.searchAlgorithm.search(regex, chars, p, end, range);
+ p = regex.searchAlgorithm.search(regex, ch, p, e, range);
if (p != -1 && p < range) {
if (p - regex.dMin < s) {
@@ -119,9 +120,9 @@ public abstract class Matcher extends IntHolder {
if (regex.subAnchor != 0) {
switch (regex.subAnchor) {
case AnchorType.BEGIN_LINE:
- if (p != str) {
- int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
- if (!EncodingHelper.isNewLine(chars, prev, end)) {
+ if (p != string) {
+ final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p);
+ if (!EncodingHelper.isNewLine(ch, prev, e)) {
// goto retry_gate;
pprev = p;
p++;
@@ -131,17 +132,17 @@ public abstract class Matcher extends IntHolder {
break;
case AnchorType.END_LINE:
- if (p == end) {
+ if (p == e) {
if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
- int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
- if (prev != -1 && EncodingHelper.isNewLine(chars, prev, end)) {
+ final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p);
+ if (prev != -1 && EncodingHelper.isNewLine(ch, prev, e)) {
// goto retry_gate;
pprev = p;
p++;
continue retry;
}
}
- } else if (!EncodingHelper.isNewLine(chars, p, end)) {
+ } else if (!EncodingHelper.isNewLine(ch, p, e)) {
//if () break;
// goto retry_gate;
pprev = p;
@@ -149,6 +150,9 @@ public abstract class Matcher extends IntHolder {
continue retry;
}
break;
+
+ default:
+ break;
} // switch
}
@@ -158,7 +162,7 @@ public abstract class Matcher extends IntHolder {
if (low > s) {
lowPrev.value = EncodingHelper.prevCharHead(s, p);
} else {
- lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
+ lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p);
}
}
} else {
@@ -172,7 +176,7 @@ public abstract class Matcher extends IntHolder {
}
} else {
if (lowPrev != null) {
- lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, low);
+ lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, low);
}
}
}
@@ -182,8 +186,8 @@ public abstract class Matcher extends IntHolder {
if (Config.DEBUG_SEARCH) {
Config.log.println("forward_search_range success: "+
- "low: " + (low - str) +
- ", high: " + (high - str) +
+ "low: " + (low - string) +
+ ", high: " + (high - string) +
", dmin: " + regex.dMin +
", dmax: " + regex.dMax);
}
@@ -196,20 +200,21 @@ public abstract class Matcher extends IntHolder {
}
// low, high
- private boolean backwardSearchRange(char[] chars, int str, int end, int s, int range, int adjrange) {
- range += regex.dMin;
+ private boolean backwardSearchRange(final char[] ch, final int string, final int e, final int s, final int range, final int adjrange) {
+ int r = range;
+ r += regex.dMin;
int p = s;
retry:while (true) {
- p = regex.searchAlgorithm.searchBackward(regex, chars, range, adjrange, end, p, s, range);
+ p = regex.searchAlgorithm.searchBackward(regex, ch, r, adjrange, e, p, s, r);
if (p != -1) {
if (regex.subAnchor != 0) {
switch (regex.subAnchor) {
case AnchorType.BEGIN_LINE:
- if (p != str) {
- int prev = EncodingHelper.prevCharHead(str, p);
- if (!EncodingHelper.isNewLine(chars, prev, end)) {
+ if (p != string) {
+ final int prev = EncodingHelper.prevCharHead(string, p);
+ if (!EncodingHelper.isNewLine(ch, prev, e)) {
p = prev;
continue retry;
}
@@ -217,21 +222,28 @@ public abstract class Matcher extends IntHolder {
break;
case AnchorType.END_LINE:
- if (p == end) {
+ if (p == e) {
if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
- int prev = EncodingHelper.prevCharHead(adjrange, p);
- if (prev == -1) return false;
- if (EncodingHelper.isNewLine(chars, prev, end)) {
+ final int prev = EncodingHelper.prevCharHead(adjrange, p);
+ if (prev == -1) {
+ return false;
+ }
+ if (EncodingHelper.isNewLine(ch, prev, e)) {
p = prev;
continue retry;
}
}
- } else if (!EncodingHelper.isNewLine(chars, p, end)) {
+ } else if (!EncodingHelper.isNewLine(ch, p, e)) {
p = EncodingHelper.prevCharHead(adjrange, p);
- if (p == -1) return false;
+ if (p == -1) {
+ return false;
+ }
continue retry;
}
break;
+
+ default:
+ break;
} // switch
}
@@ -243,48 +255,59 @@ public abstract class Matcher extends IntHolder {
if (Config.DEBUG_SEARCH) {
Config.log.println("backward_search_range: "+
- "low: " + (low - str) +
- ", high: " + (high - str));
+ "low: " + (low - string) +
+ ", high: " + (high - string));
}
return true;
}
- if (Config.DEBUG_SEARCH) Config.log.println("backward_search_range: fail.");
+ if (Config.DEBUG_SEARCH) {
+ Config.log.println("backward_search_range: fail.");
+ }
return false;
} // while
}
// MATCH_AND_RETURN_CHECK
- private boolean matchCheck(int upperRange, int s, int prev) {
+ private boolean matchCheck(final int upperRange, final int s, final int prev) {
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
//range = upperRange;
if (matchAt(upperRange, s, prev) != -1) {
- if (!isFindLongest(regex.options)) return true;
+ if (!isFindLongest(regex.options)) {
+ return true;
+ }
}
} else {
//range = upperRange;
- if (matchAt(upperRange, s, prev) != -1) return true;
+ if (matchAt(upperRange, s, prev) != -1) {
+ return true;
+ }
}
} else {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
if (matchAt(end, s, prev) != -1) {
//range = upperRange;
- if (!isFindLongest(regex.options)) return true;
+ if (!isFindLongest(regex.options)) {
+ return true;
+ }
}
} else {
//range = upperRange;
- if (matchAt(end, s, prev) != -1) return true;
+ if (matchAt(end, s, prev) != -1) {
+ return true;
+ }
}
}
return false;
}
- public final int search(int start, int range, int option) {
+ public final int search(final int startp, final int rangep, final int option) {
+ int start = startp, range = rangep;
int s, prev;
int origStart = start;
- int origRange = range;
+ final int origRange = range;
if (Config.DEBUG_SEARCH) {
Config.log.println("onig_search (entry point): "+
@@ -294,7 +317,9 @@ public abstract class Matcher extends IntHolder {
", range " + (range - str));
}
- if (start > end || start < str) return -1;
+ if (start > end || start < str) {
+ return -1;
+ }
/* anchor optimize: resume search range */
if (regex.anchor != 0 && str < end) {
@@ -311,7 +336,10 @@ public abstract class Matcher extends IntHolder {
} else if ((regex.anchor & AnchorType.BEGIN_BUF) != 0) {
/* search str-position only */
if (range > start) {
- if (start != str) return -1; // mismatch_no_msa;
+ if (start != str)
+ {
+ return -1; // mismatch_no_msa;
+ }
range = str + 1;
} else {
if (range <= str) {
@@ -324,20 +352,29 @@ public abstract class Matcher extends IntHolder {
} else if ((regex.anchor & AnchorType.END_BUF) != 0) {
minSemiEnd = maxSemiEnd = end;
// !end_buf:!
- if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa;
+ if (endBuf(start, range, minSemiEnd, maxSemiEnd))
+ {
+ return -1; // mismatch_no_msa;
+ }
} else if ((regex.anchor & AnchorType.SEMI_END_BUF) != 0) {
- int preEnd = EncodingHelper.stepBack(str, end, 1);
+ final int preEnd = EncodingHelper.stepBack(str, end, 1);
maxSemiEnd = end;
if (EncodingHelper.isNewLine(chars, preEnd, end)) {
minSemiEnd = preEnd;
if (minSemiEnd > str && start <= minSemiEnd) {
// !goto end_buf;!
- if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa;
+ if (endBuf(start, range, minSemiEnd, maxSemiEnd))
+ {
+ return -1; // mismatch_no_msa;
+ }
}
} else {
minSemiEnd = end;
// !goto end_buf;!
- if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa;
+ if (endBuf(start, range, minSemiEnd, maxSemiEnd))
+ {
+ return -1; // mismatch_no_msa;
+ }
}
} else if ((regex.anchor & AnchorType.ANYCHAR_STAR_ML) != 0) {
// goto !begin_position;!
@@ -359,7 +396,9 @@ public abstract class Matcher extends IntHolder {
prev = -1;
msaInit(option, start);
- if (matchCheck(end, s, prev)) return match(s);
+ if (matchCheck(end, s, prev)) {
+ return match(s);
+ }
return mismatch();
}
return -1; // goto mismatch_no_msa;
@@ -389,49 +428,62 @@ public abstract class Matcher extends IntHolder {
schRange = end;
} else {
schRange += regex.dMax;
- if (schRange > end) schRange = end;
+ if (schRange > end) {
+ schRange = end;
+ }
}
}
- if ((end - start) < regex.thresholdLength) return mismatch();
+ if ((end - start) < regex.thresholdLength) {
+ return mismatch();
+ }
if (regex.dMax != MinMaxLen.INFINITE_DISTANCE) {
do {
- if (!forwardSearchRange(chars, str, end, s, schRange, this)) return mismatch(); // low, high, lowPrev
+ if (!forwardSearchRange(chars, str, end, s, schRange, this)) {
+ return mismatch(); // low, high, lowPrev
+ }
if (s < low) {
s = low;
prev = value;
}
while (s <= high) {
- if (matchCheck(origRange, s, prev)) return match(s); // ???
+ if (matchCheck(origRange, s, prev)) {
+ return match(s); // ???
+ }
prev = s;
s++;
}
} while (s < range);
+ }
+ /* check only. */
+ if (!forwardSearchRange(chars, str, end, s, schRange, null)) {
return mismatch();
+ }
- } else { /* check only. */
- if (!forwardSearchRange(chars, str, end, s, schRange, null)) return mismatch();
-
- if ((regex.anchor & AnchorType.ANYCHAR_STAR) != 0) {
- do {
- if (matchCheck(origRange, s, prev)) return match(s);
- prev = s;
- s++;
- } while (s < range);
- return mismatch();
- }
-
+ if ((regex.anchor & AnchorType.ANYCHAR_STAR) != 0) {
+ do {
+ if (matchCheck(origRange, s, prev)) {
+ return match(s);
+ }
+ prev = s;
+ s++;
+ } while (s < range);
+ return mismatch();
}
}
do {
- if (matchCheck(origRange, s, prev)) return match(s);
+ if (matchCheck(origRange, s, prev)) {
+ return match(s);
+ }
prev = s;
s++;
} while (s < range);
if (s == range) { /* because empty match with /$/. */
- if (matchCheck(origRange, s, prev)) return match(s);
+ if (matchCheck(origRange, s, prev)) {
+ return match(s);
+ }
}
} else { /* backward search */
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
@@ -450,37 +502,51 @@ public abstract class Matcher extends IntHolder {
if (regex.dMax != MinMaxLen.INFINITE_DISTANCE && (end - range) >= regex.thresholdLength) {
do {
int schStart = s + regex.dMax;
- if (schStart > end) schStart = end;
- if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) return mismatch(); // low, high
- if (s > high) s = high;
+ if (schStart > end) {
+ schStart = end;
+ }
+ if (!backwardSearchRange(chars, str, end, schStart, range, adjrange))
+ {
+ return mismatch(); // low, high
+ }
+ if (s > high) {
+ s = high;
+ }
while (s != -1 && s >= low) {
prev = EncodingHelper.prevCharHead(str, s);
- if (matchCheck(origStart, s, prev)) return match(s);
+ if (matchCheck(origStart, s, prev)) {
+ return match(s);
+ }
s = prev;
}
} while (s >= range);
return mismatch();
- } else { /* check only. */
- if ((end - range) < regex.thresholdLength) return mismatch();
+ }
+ if ((end - range) < regex.thresholdLength) {
+ return mismatch();
+ }
- int schStart = s;
- if (regex.dMax != 0) {
- if (regex.dMax == MinMaxLen.INFINITE_DISTANCE) {
+ int schStart = s;
+ if (regex.dMax != 0) {
+ if (regex.dMax == MinMaxLen.INFINITE_DISTANCE) {
+ schStart = end;
+ } else {
+ schStart += regex.dMax;
+ if (schStart > end) {
schStart = end;
- } else {
- schStart += regex.dMax;
- if (schStart > end) {
- schStart = end;
- }
}
}
- if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) return mismatch();
+ }
+ if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) {
+ return mismatch();
}
}
do {
prev = EncodingHelper.prevCharHead(str, s);
- if (matchCheck(origStart, s, prev)) return match(s);
+ if (matchCheck(origStart, s, prev)) {
+ return match(s);
+ }
s = prev;
} while (s >= range);
@@ -488,8 +554,13 @@ public abstract class Matcher extends IntHolder {
return mismatch();
}
- private boolean endBuf(int start, int range, int minSemiEnd, int maxSemiEnd) {
- if ((maxSemiEnd - str) < regex.anchorDmin) return true; // mismatch_no_msa;
+ private boolean endBuf(final int startp, final int rangep, final int minSemiEnd, final int maxSemiEnd) {
+ int start = startp;
+ int range = rangep;
+
+ if ((maxSemiEnd - str) < regex.anchorDmin) {
+ return true; // mismatch_no_msa;
+ }
if (range > start) {
if ((minSemiEnd - start) > regex.anchorDmax) {
@@ -502,7 +573,10 @@ public abstract class Matcher extends IntHolder {
if ((maxSemiEnd - (range - 1)) < regex.anchorDmin) {
range = maxSemiEnd - regex.anchorDmin + 1;
}
- if (start >= range) return true; // mismatch_no_msa;
+ if (start >= range)
+ {
+ return true; // mismatch_no_msa;
+ }
} else {
if ((minSemiEnd - range) > regex.anchorDmax) {
range = minSemiEnd - regex.anchorDmax;
@@ -510,19 +584,22 @@ public abstract class Matcher extends IntHolder {
if ((maxSemiEnd - start) < regex.anchorDmin) {
start = maxSemiEnd - regex.anchorDmin;
}
- if (range > start) return true; // mismatch_no_msa;
+ if (range > start)
+ {
+ return true; // mismatch_no_msa;
+ }
}
return false;
}
- private int match(int s) {
+ private int match(final int s) {
return s - str; // sstart ???
}
private int mismatch() {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
if (msaBestLen >= 0) {
- int s = msaBestS;
+ final int s = msaBestS;
return match(s);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java b/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
index f507018f..70642d5e 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
@@ -19,12 +19,13 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public abstract class MatcherFactory {
public abstract Matcher create(Regex regex, char[] chars, int p, int end);
static final MatcherFactory DEFAULT = new MatcherFactory() {
@Override
- public Matcher create(Regex regex, char[] chars, int p, int end) {
+ public Matcher create(final Regex regex, final char[] chars, final int p, final int end) {
return new ByteCodeMachine(regex, chars, p, end);
}
};
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java b/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
index 388c0c52..83a9e2dc 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
@@ -26,7 +26,7 @@ final class MinMaxLen {
MinMaxLen() {
}
- MinMaxLen(int min, int max) {
+ MinMaxLen(final int min, final int max) {
this.min = min;
this.max = max;
}
@@ -46,32 +46,48 @@ final class MinMaxLen {
};
int distanceValue() {
- if (max == INFINITE_DISTANCE) return 0;
- int d = max - min;
+ if (max == INFINITE_DISTANCE) {
+ return 0;
+ }
+ final int d = max - min;
/* return dist_vals[d] * 16 / (mm->min + 12); */
return d < distValues.length ? distValues[d] : 1;
}
- int compareDistanceValue(MinMaxLen other, int v1, int v2) {
- if (v2 <= 0) return -1;
- if (v1 <= 0) return 1;
+ int compareDistanceValue(final MinMaxLen other, final int v1p, final int v2p) {
+ int v1 = v1p, v2 = v2p;
+
+ if (v2 <= 0) {
+ return -1;
+ }
+ if (v1 <= 0) {
+ return 1;
+ }
v1 *= distanceValue();
v2 *= other.distanceValue();
- if (v2 > v1) return 1;
- if (v2 < v1) return -1;
+ if (v2 > v1) {
+ return 1;
+ }
+ if (v2 < v1) {
+ return -1;
+ }
- if (other.min < min) return 1;
- if (other.min > min) return -1;
+ if (other.min < min) {
+ return 1;
+ }
+ if (other.min > min) {
+ return -1;
+ }
return 0;
}
- boolean equal(MinMaxLen other) {
+ boolean equal(final MinMaxLen other) {
return min == other.min && max == other.max;
}
- void set(int min, int max) {
+ void set(final int min, final int max) {
this.min = min;
this.max = max;
}
@@ -80,46 +96,52 @@ final class MinMaxLen {
min = max = 0;
}
- void copy(MinMaxLen other) {
+ void copy(final MinMaxLen other) {
min = other.min;
max = other.max;
}
- void add(MinMaxLen other) {
+ void add(final MinMaxLen other) {
min = distanceAdd(min, other.min);
max = distanceAdd(max, other.max);
}
- void addLength(int len) {
+ void addLength(final int len) {
min = distanceAdd(min, len);
max = distanceAdd(max, len);
}
- void altMerge(MinMaxLen other) {
- if (min > other.min) min = other.min;
- if (max < other.max) max = other.max;
+ void altMerge(final MinMaxLen other) {
+ if (min > other.min) {
+ min = other.min;
+ }
+ if (max < other.max) {
+ max = other.max;
+ }
}
static final int INFINITE_DISTANCE = 0x7FFFFFFF;
- static int distanceAdd(int d1, int d2) {
+ static int distanceAdd(final int d1, final int d2) {
if (d1 == INFINITE_DISTANCE || d2 == INFINITE_DISTANCE) {
return INFINITE_DISTANCE;
- } else {
- if (d1 <= INFINITE_DISTANCE - d2) return d1 + d2;
- else return INFINITE_DISTANCE;
}
+ if (d1 <= INFINITE_DISTANCE - d2) {
+ return d1 + d2;
+ }
+ return INFINITE_DISTANCE;
}
- static int distanceMultiply(int d, int m) {
- if (m == 0) return 0;
+ static int distanceMultiply(final int d, final int m) {
+ if (m == 0) {
+ return 0;
+ }
if (d < INFINITE_DISTANCE / m) {
return d * m;
- } else {
- return INFINITE_DISTANCE;
}
+ return INFINITE_DISTANCE;
}
- static String distanceRangeToString(int a, int b) {
+ static String distanceRangeToString(final int a, final int b) {
String s = "";
if (a == INFINITE_DISTANCE) {
s += "inf";
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
index 76b1d5f6..a5e569dc 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public final class NodeOptInfo {
final MinMaxLen length = new MinMaxLen();
final OptAnchorInfo anchor = new OptAnchorInfo();
@@ -27,7 +28,7 @@ public final class NodeOptInfo {
final OptExactInfo expr = new OptExactInfo(); /* prec read (?=...) */
final OptMapInfo map = new OptMapInfo(); /* boundary */
- public void setBoundNode(MinMaxLen mmd) {
+ public void setBoundNode(final MinMaxLen mmd) {
exb.mmd.copy(mmd);
expr.mmd.copy(mmd);
map.mmd.copy(mmd);
@@ -42,7 +43,7 @@ public final class NodeOptInfo {
map.clear();
}
- public void copy(NodeOptInfo other) {
+ public void copy(final NodeOptInfo other) {
length.copy(other.length);
anchor.copy(other.anchor);
exb.copy(other.exb);
@@ -51,8 +52,8 @@ public final class NodeOptInfo {
map.copy(other.map);
}
- public void concatLeftNode(NodeOptInfo other) {
- OptAnchorInfo tanchor = new OptAnchorInfo(); // remove it somehow ?
+ public void concatLeftNode(final NodeOptInfo other) {
+ final OptAnchorInfo tanchor = new OptAnchorInfo(); // remove it somehow ?
tanchor.concat(anchor, other.anchor, length.max, other.length.max);
anchor.copy(tanchor);
@@ -67,8 +68,8 @@ public final class NodeOptInfo {
}
}
- boolean exbReach = exb.reachEnd;
- boolean exmReach = exm.reachEnd;
+ final boolean exbReach = exb.reachEnd;
+ final boolean exmReach = exm.reachEnd;
if (other.length.max != 0) {
exb.reachEnd = exm.reachEnd = false;
@@ -91,8 +92,12 @@ public final class NodeOptInfo {
if (other.length.max > 0) {
// TODO: make sure it is not an Oniguruma bug (casting unsigned int to int for arithmetic comparison)
int otherLengthMax = other.length.max;
- if (otherLengthMax == MinMaxLen.INFINITE_DISTANCE) otherLengthMax = -1;
- if (expr.length > otherLengthMax) expr.length = otherLengthMax;
+ if (otherLengthMax == MinMaxLen.INFINITE_DISTANCE) {
+ otherLengthMax = -1;
+ }
+ if (expr.length > otherLengthMax) {
+ expr.length = otherLengthMax;
+ }
if (expr.mmd.max == 0) {
exb.select(expr);
} else {
@@ -107,7 +112,7 @@ public final class NodeOptInfo {
length.add(other.length);
}
- public void altMerge(NodeOptInfo other, OptEnvironment env) {
+ public void altMerge(final NodeOptInfo other, final OptEnvironment env) {
anchor.altMerge(other.anchor);
exb.altMerge(other.exb, env);
exm.altMerge(other.exm, env);
@@ -116,7 +121,7 @@ public final class NodeOptInfo {
length.altMerge(other.length);
}
- public void setBound(MinMaxLen mmd) {
+ public void setBound(final MinMaxLen mmd) {
exb.mmd.copy(mmd);
expr.mmd.copy(mmd);
map.mmd.copy(mmd);
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
index 4ed24e0b..7c7f5140 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
@@ -29,25 +29,31 @@ final class OptAnchorInfo implements AnchorType {
leftAnchor = rightAnchor = 0;
}
- void copy(OptAnchorInfo other) {
+ void copy(final OptAnchorInfo other) {
leftAnchor = other.leftAnchor;
rightAnchor = other.rightAnchor;
}
- void concat(OptAnchorInfo left, OptAnchorInfo right, int leftLength, int rightLength) {
+ void concat(final OptAnchorInfo left, final OptAnchorInfo right, final int leftLength, final int rightLength) {
leftAnchor = left.leftAnchor;
- if (leftLength == 0) leftAnchor |= right.leftAnchor;
+ if (leftLength == 0) {
+ leftAnchor |= right.leftAnchor;
+ }
rightAnchor = right.rightAnchor;
- if (rightLength == 0) rightAnchor |= left.rightAnchor;
+ if (rightLength == 0) {
+ rightAnchor |= left.rightAnchor;
+ }
}
- boolean isSet(int anchor) {
- if ((leftAnchor & anchor) != 0) return true;
+ boolean isSet(final int anchor) {
+ if ((leftAnchor & anchor) != 0) {
+ return true;
+ }
return (rightAnchor & anchor) != 0;
}
- void add(int anchor) {
+ void add(final int anchor) {
if (isLeftAnchor(anchor)) {
leftAnchor |= anchor;
} else {
@@ -55,7 +61,7 @@ final class OptAnchorInfo implements AnchorType {
}
}
- void remove(int anchor) {
+ void remove(final int anchor) {
if (isLeftAnchor(anchor)) {
leftAnchor &= ~anchor;
} else {
@@ -63,28 +69,44 @@ final class OptAnchorInfo implements AnchorType {
}
}
- void altMerge(OptAnchorInfo other) {
+ void altMerge(final OptAnchorInfo other) {
leftAnchor &= other.leftAnchor;
rightAnchor &= other.rightAnchor;
}
- static boolean isLeftAnchor(int anchor) { // make a mask for it ?
+ static boolean isLeftAnchor(final int anchor) { // make a mask for it ?
return !(anchor == END_BUF || anchor == SEMI_END_BUF ||
anchor == END_LINE || anchor == PREC_READ ||
anchor == PREC_READ_NOT);
}
- static String anchorToString(int anchor) {
- StringBuffer s = new StringBuffer("[");
+ static String anchorToString(final int anchor) {
+ final StringBuffer s = new StringBuffer("[");
- if ((anchor & AnchorType.BEGIN_BUF) !=0 ) s.append("begin-buf ");
- if ((anchor & AnchorType.BEGIN_LINE) !=0 ) s.append("begin-line ");
- if ((anchor & AnchorType.BEGIN_POSITION) !=0 ) s.append("begin-pos ");
- if ((anchor & AnchorType.END_BUF) !=0 ) s.append("end-buf ");
- if ((anchor & AnchorType.SEMI_END_BUF) !=0 ) s.append("semi-end-buf ");
- if ((anchor & AnchorType.END_LINE) !=0 ) s.append("end-line ");
- if ((anchor & AnchorType.ANYCHAR_STAR) !=0 ) s.append("anychar-star ");
- if ((anchor & AnchorType.ANYCHAR_STAR_ML) !=0 ) s.append("anychar-star-pl ");
+ if ((anchor & AnchorType.BEGIN_BUF) !=0 ) {
+ s.append("begin-buf ");
+ }
+ if ((anchor & AnchorType.BEGIN_LINE) !=0 ) {
+ s.append("begin-line ");
+ }
+ if ((anchor & AnchorType.BEGIN_POSITION) !=0 ) {
+ s.append("begin-pos ");
+ }
+ if ((anchor & AnchorType.END_BUF) !=0 ) {
+ s.append("end-buf ");
+ }
+ if ((anchor & AnchorType.SEMI_END_BUF) !=0 ) {
+ s.append("semi-end-buf ");
+ }
+ if ((anchor & AnchorType.END_LINE) !=0 ) {
+ s.append("end-line ");
+ }
+ if ((anchor & AnchorType.ANYCHAR_STAR) !=0 ) {
+ s.append("anychar-star ");
+ }
+ if ((anchor & AnchorType.ANYCHAR_STAR_ML) !=0 ) {
+ s.append("anychar-star-pl ");
+ }
s.append("]");
return s.toString();
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java b/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
index 8c75e03d..ba1eb136 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
@@ -26,7 +26,7 @@ final class OptEnvironment {
int caseFoldFlag;
ScanEnvironment scanEnv;
- void copy(OptEnvironment other) {
+ void copy(final OptEnvironment other) {
mmd.copy(other.mmd);
options = other.options;
caseFoldFlag = other.caseFoldFlag;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
index f7992a32..cc2143de 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
@@ -44,7 +44,7 @@ final class OptExactInfo {
length = 0;
}
- void copy(OptExactInfo other) {
+ void copy(final OptExactInfo other) {
mmd.copy(other.mmd);
anchor.copy(other.anchor);
reachEnd = other.reachEnd;
@@ -54,42 +54,51 @@ final class OptExactInfo {
System.arraycopy(other.chars, 0, chars, 0, OPT_EXACT_MAXLEN);
}
- void concat(OptExactInfo other) {
+ void concat(final OptExactInfo other) {
if (!ignoreCase && other.ignoreCase) {
- if (length >= other.length) return; /* avoid */
+ if (length >= other.length) {
+ return; /* avoid */
+ }
ignoreCase = true;
}
int p = 0; // add->s;
- int end = p + other.length;
+ final int end = p + other.length;
int i;
for (i = length; p < end;) {
- if (i + 1 > OPT_EXACT_MAXLEN) break;
+ if (i + 1 > OPT_EXACT_MAXLEN) {
+ break;
+ }
chars[i++] = other.chars[p++];
}
length = i;
reachEnd = (p == end ? other.reachEnd : false);
- OptAnchorInfo tmp = new OptAnchorInfo();
+ final OptAnchorInfo tmp = new OptAnchorInfo();
tmp.concat(anchor, other.anchor, 1, 1);
- if (!other.reachEnd) tmp.rightAnchor = 0;
+ if (!other.reachEnd) {
+ tmp.rightAnchor = 0;
+ }
anchor.copy(tmp);
}
// ?? raw is not used here
- void concatStr(char[] lchars, int p, int end, boolean raw) {
+ void concatStr(final char[] lchars, final int pp, final int end, final boolean raw) {
int i;
+ int p = pp;
for (i = length; p < end && i < OPT_EXACT_MAXLEN;) {
- if (i + 1 > OPT_EXACT_MAXLEN) break;
+ if (i + 1 > OPT_EXACT_MAXLEN) {
+ break;
+ }
chars[i++] = lchars[p++];
}
length = i;
}
- void altMerge(OptExactInfo other, OptEnvironment env) {
+ void altMerge(final OptExactInfo other, final OptEnvironment env) {
if (other.length == 0 || length == 0) {
clear();
return;
@@ -102,21 +111,27 @@ final class OptExactInfo {
int i;
for (i = 0; i < length && i < other.length; i++) {
- if (chars[i] != other.chars[i]) break;
+ if (chars[i] != other.chars[i]) {
+ break;
+ }
}
- if (!other.reachEnd || i<other.length || i<length) reachEnd = false;
+ if (!other.reachEnd || i<other.length || i<length) {
+ reachEnd = false;
+ }
length = i;
ignoreCase |= other.ignoreCase;
anchor.altMerge(other.anchor);
- if (!reachEnd) anchor.rightAnchor = 0;
+ if (!reachEnd) {
+ anchor.rightAnchor = 0;
+ }
}
- void select(OptExactInfo alt) {
+ void select(final OptExactInfo alt) {
int v1 = length;
int v2 = alt.length;
@@ -130,23 +145,35 @@ final class OptExactInfo {
v2 = OptMapInfo.positionValue(chars[0] & 0xff);
v1 = OptMapInfo.positionValue(alt.chars[0] & 0xff);
- if (length > 1) v1 += 5;
- if (alt.length > 1) v2 += 5;
+ if (length > 1) {
+ v1 += 5;
+ }
+ if (alt.length > 1) {
+ v2 += 5;
+ }
}
- if (!ignoreCase) v1 *= 2;
- if (!alt.ignoreCase) v2 *= 2;
+ if (!ignoreCase) {
+ v1 *= 2;
+ }
+ if (!alt.ignoreCase) {
+ v2 *= 2;
+ }
- if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) copy(alt);
+ if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) {
+ copy(alt);
+ }
}
// comp_opt_exact_or_map_info
private static final int COMP_EM_BASE = 20;
- int compare(OptMapInfo m) {
- if (m.value <= 0) return -1;
+ int compare(final OptMapInfo m) {
+ if (m.value <= 0) {
+ return -1;
+ }
- int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
- int vm = COMP_EM_BASE * 5 * 2 / m.value;
+ final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
+ final int vm = COMP_EM_BASE * 5 * 2 / m.value;
return mmd.compareDistanceValue(m.mmd, ve, vm);
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
index 9cf6a50d..a3c4c7c5 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
@@ -31,10 +31,12 @@ final class OptMapInfo {
mmd.clear();
anchor.clear();
value = 0;
- for (int i=0; i<map.length; i++) map[i] = 0;
+ for (int i=0; i<map.length; i++) {
+ map[i] = 0;
+ }
}
- void copy(OptMapInfo other) {
+ void copy(final OptMapInfo other) {
mmd.copy(other.mmd);
anchor.copy(other.anchor);
value = other.value;
@@ -42,19 +44,18 @@ final class OptMapInfo {
System.arraycopy(other.map, 0, map, 0, other.map.length);
}
- void addChar(int c) {
- int c_ = c & 0xff;
+ void addChar(final int c) {
+ final int c_ = c & 0xff;
if (map[c_] == 0) {
map[c_] = 1;
value += positionValue(c_);
}
}
- void addCharAmb(char[] chars, int p, int end, int caseFoldFlag) {
+ void addCharAmb(final char[] chars, final int p, final int end, final int caseFoldFlag) {
addChar(chars[p]);
- caseFoldFlag &= ~Config.INTERNAL_ENC_CASE_FOLD_MULTI_CHAR;
- char[]items = EncodingHelper.caseFoldCodesByString(caseFoldFlag, chars[p]);
+ final char[]items = EncodingHelper.caseFoldCodesByString(caseFoldFlag & ~Config.INTERNAL_ENC_CASE_FOLD_MULTI_CHAR, chars[p]);
for (int i=0; i<items.length; i++) {
addChar(items[i]);
@@ -63,23 +64,29 @@ final class OptMapInfo {
// select_opt_map_info
private static final int z = 1<<15; /* 32768: something big value */
- void select(OptMapInfo alt) {
- if (alt.value == 0) return;
+ void select(final OptMapInfo alt) {
+ if (alt.value == 0) {
+ return;
+ }
if (value == 0) {
copy(alt);
return;
}
- int v1 = z / value;
- int v2 = z /alt.value;
+ final int v1 = z / value;
+ final int v2 = z /alt.value;
- if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) copy(alt);
+ if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) {
+ copy(alt);
+ }
}
// alt_merge_opt_map_info
- void altMerge(OptMapInfo other) {
+ void altMerge(final OptMapInfo other) {
/* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
- if (value == 0) return;
+ if (value == 0) {
+ return;
+ }
if (other.value == 0 || mmd.max < other.mmd.max) {
clear();
return;
@@ -89,8 +96,12 @@ final class OptMapInfo {
int val = 0;
for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) {
- if (other.map[i] != 0) map[i] = 1;
- if (map[i] != 0) val += positionValue(i);
+ if (other.map[i] != 0) {
+ map[i] = 1;
+ }
+ if (map[i] != 0) {
+ val += positionValue(i);
+ }
}
value = val;
@@ -109,12 +120,11 @@ final class OptMapInfo {
};
// map_position_value
- static int positionValue(int i) {
+ static int positionValue(final int i) {
if (i < ByteValTable.length) {
return ByteValTable[i];
- } else {
- return 4; /* Take it easy. */
}
+ return 4; /* Take it easy. */
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
index 26f3e560..ead99007 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public class Option {
/* options */
@@ -41,74 +42,98 @@ public class Option {
public static final int DEFAULT = NONE;
- public static String toString(int option) {
+ public static String toString(final int option) {
String options = "";
- if (isIgnoreCase(option)) options += "IGNORECASE ";
- if (isExtend(option)) options += "EXTEND ";
- if (isMultiline(option)) options += "MULTILINE ";
- if (isSingleline(option)) options += "SINGLELINE ";
- if (isFindLongest(option)) options += "FIND_LONGEST ";
- if (isFindNotEmpty(option)) options += "FIND_NOT_EMPTY ";
- if (isNegateSingleline(option)) options += "NEGATE_SINGLELINE ";
- if (isDontCaptureGroup(option)) options += "DONT_CAPTURE_GROUP ";
- if (isCaptureGroup(option)) options += "CAPTURE_GROUP ";
-
- if (isNotBol(option)) options += "NOTBOL ";
- if (isNotEol(option)) options += "NOTEOL ";
- if (isPosixRegion(option)) options += "POSIX_REGION ";
+ if (isIgnoreCase(option)) {
+ options += "IGNORECASE ";
+ }
+ if (isExtend(option)) {
+ options += "EXTEND ";
+ }
+ if (isMultiline(option)) {
+ options += "MULTILINE ";
+ }
+ if (isSingleline(option)) {
+ options += "SINGLELINE ";
+ }
+ if (isFindLongest(option)) {
+ options += "FIND_LONGEST ";
+ }
+ if (isFindNotEmpty(option)) {
+ options += "FIND_NOT_EMPTY ";
+ }
+ if (isNegateSingleline(option)) {
+ options += "NEGATE_SINGLELINE ";
+ }
+ if (isDontCaptureGroup(option)) {
+ options += "DONT_CAPTURE_GROUP ";
+ }
+ if (isCaptureGroup(option)) {
+ options += "CAPTURE_GROUP ";
+ }
+
+ if (isNotBol(option)) {
+ options += "NOTBOL ";
+ }
+ if (isNotEol(option)) {
+ options += "NOTEOL ";
+ }
+ if (isPosixRegion(option)) {
+ options += "POSIX_REGION ";
+ }
return options;
}
- public static boolean isIgnoreCase(int option) {
+ public static boolean isIgnoreCase(final int option) {
return (option & IGNORECASE) != 0;
}
- public static boolean isExtend(int option) {
+ public static boolean isExtend(final int option) {
return (option & EXTEND) != 0;
}
- public static boolean isSingleline(int option) {
+ public static boolean isSingleline(final int option) {
return (option & SINGLELINE) != 0;
}
- public static boolean isMultiline(int option) {
+ public static boolean isMultiline(final int option) {
return (option & MULTILINE) != 0;
}
- public static boolean isFindLongest(int option) {
+ public static boolean isFindLongest(final int option) {
return (option & FIND_LONGEST) != 0;
}
- public static boolean isFindNotEmpty(int option) {
+ public static boolean isFindNotEmpty(final int option) {
return (option & FIND_NOT_EMPTY) != 0;
}
- public static boolean isFindCondition(int option) {
+ public static boolean isFindCondition(final int option) {
return (option & (FIND_LONGEST | FIND_NOT_EMPTY)) != 0;
}
- public static boolean isNegateSingleline(int option) {
+ public static boolean isNegateSingleline(final int option) {
return (option & NEGATE_SINGLELINE) != 0;
}
- public static boolean isDontCaptureGroup(int option) {
+ public static boolean isDontCaptureGroup(final int option) {
return (option & DONT_CAPTURE_GROUP) != 0;
}
- public static boolean isCaptureGroup(int option) {
+ public static boolean isCaptureGroup(final int option) {
return (option & CAPTURE_GROUP) != 0;
}
- public static boolean isNotBol(int option) {
+ public static boolean isNotBol(final int option) {
return (option & NOTBOL) != 0;
}
- public static boolean isNotEol(int option) {
+ public static boolean isNotEol(final int option) {
return (option & NOTEOL) != 0;
}
- public static boolean isPosixRegion(int option) {
+ public static boolean isPosixRegion(final int option) {
return (option & POSIX_REGION) != 0;
}
@@ -116,7 +141,7 @@ public class Option {
// public static boolean isDynamic(int option) {
// return (option & (MULTILINE | IGNORECASE)) != 0;
// }
- public static boolean isDynamic(int option) {
+ public static boolean isDynamic(final int option) {
return false;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
index 2cbd0fce..9960899d 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
@@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
@@ -52,7 +51,7 @@ class Parser extends Lexer {
protected int returnCode; // return code used by parser methods (they itself return parsed nodes)
// this approach will not affect recursive calls
- protected Parser(ScanEnvironment env, char[] chars, int p, int end) {
+ protected Parser(final ScanEnvironment env, final char[] chars, final int p, final int end) {
super(env, chars, p, end);
regex = env.reg;
}
@@ -64,7 +63,7 @@ class Parser extends Lexer {
return root;
}
- private boolean codeExistCheck(int code, boolean ignoreEscaped) {
+ private boolean codeExistCheck(final int code, final boolean ignoreEscaped) {
mark();
boolean inEsc = false;
@@ -77,7 +76,9 @@ class Parser extends Lexer {
restore();
return true;
}
- if (c == syntax.metaCharTable.esc) inEsc = true;
+ if (c == syntax.metaCharTable.esc) {
+ inEsc = true;
+ }
}
}
@@ -108,7 +109,7 @@ class Parser extends Lexer {
CClassNode prevCC = null;
CClassNode workCC = null;
- CCStateArg arg = new CCStateArg();
+ final CCStateArg arg = new CCStateArg();
boolean andStart = false;
arg.state = CCSTATE.START;
@@ -165,7 +166,9 @@ class Parser extends Lexer {
arg.vIsRaw = false;
fetchTokenInCC();
fetched = true;
- if (token.type == TokenType.CC_RANGE || andStart) env.ccEscWarn("-"); /* [--x] or [a&&-x] is warned. */
+ if (token.type == TokenType.CC_RANGE || andStart) {
+ env.ccEscWarn("-"); /* [--x] or [a&&-x] is warned. */
+ }
parseCharClassValEntry(cc, arg); // goto val_entry
break;
} else if (arg.state == CCSTATE.RANGE) {
@@ -197,7 +200,7 @@ class Parser extends Lexer {
break;
case CC_CC_OPEN: /* [ */
- CClassNode acc = parseCharClass();
+ final CClassNode acc = parseCharClass();
cc.or(acc);
break;
@@ -214,7 +217,9 @@ class Parser extends Lexer {
prevCC.and(cc);
} else {
prevCC = cc;
- if (workCC == null) workCC = new CClassNode();
+ if (workCC == null) {
+ workCC = new CClassNode();
+ }
cc = workCC;
}
cc.clear();
@@ -227,7 +232,9 @@ class Parser extends Lexer {
throw new InternalException(ERR_PARSER_BUG);
} // switch
- if (!fetched) fetchTokenInCC();
+ if (!fetched) {
+ fetchTokenInCC();
+ }
} // while
@@ -260,29 +267,29 @@ class Parser extends Lexer {
return cc;
}
- private void parseCharClassSbChar(CClassNode cc, CCStateArg arg) {
+ private void parseCharClassSbChar(final CClassNode cc, final CCStateArg arg) {
arg.inType = CCVALTYPE.SB;
arg.v = token.getC();
arg.vIsRaw = false;
parseCharClassValEntry2(cc, arg); // goto val_entry2
}
- private void parseCharClassRangeEndVal(CClassNode cc, CCStateArg arg) {
+ private void parseCharClassRangeEndVal(final CClassNode cc, final CCStateArg arg) {
arg.v = '-';
arg.vIsRaw = false;
parseCharClassValEntry(cc, arg); // goto val_entry
}
- private void parseCharClassValEntry(CClassNode cc, CCStateArg arg) {
+ private void parseCharClassValEntry(final CClassNode cc, final CCStateArg arg) {
arg.inType = arg.v <= 0xff ? CCVALTYPE.SB : CCVALTYPE.CODE_POINT;
parseCharClassValEntry2(cc, arg); // val_entry2:
}
- private void parseCharClassValEntry2(CClassNode cc, CCStateArg arg) {
+ private void parseCharClassValEntry2(final CClassNode cc, final CCStateArg arg) {
cc.nextStateValue(arg, env);
}
- private Node parseEnclose(TokenType term) {
+ private Node parseEnclose(final TokenType term) {
Node node = null;
if (!left()) {
@@ -327,8 +334,8 @@ class Parser extends Lexer {
break;
case '@':
if (syntax.op2AtMarkCaptureHistory()) {
- EncloseNode en = new EncloseNode(); // node_new_enclose_memory
- int num = env.addMemEntry();
+ final EncloseNode en = new EncloseNode(); // node_new_enclose_memory
+ final int num = env.addMemEntry();
if (num >= BitStatus.BIT_STATUS_BITS_NUM) {
throw new ValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
}
@@ -385,17 +392,17 @@ class Parser extends Lexer {
} // switch
if (c == ')') {
- EncloseNode en = new EncloseNode(option, 0); // node_new_option
+ final EncloseNode en = new EncloseNode(option, 0); // node_new_option
node = en;
returnCode = 2; /* option only */
return node;
} else if (c == ':') {
- int prev = env.option;
+ final int prev = env.option;
env.option = option;
fetchToken();
- Node target = parseSubExp(term);
+ final Node target = parseSubExp(term);
env.option = prev;
- EncloseNode en = new EncloseNode(option, 0); // node_new_option
+ final EncloseNode en = new EncloseNode(option, 0); // node_new_option
en.setTarget(target);
node = en;
returnCode = 0;
@@ -418,20 +425,20 @@ class Parser extends Lexer {
returnCode = 1; /* group */
return node;
}
- EncloseNode en = new EncloseNode(); // node_new_enclose_memory
- int num = env.addMemEntry();
+ final EncloseNode en = new EncloseNode(); // node_new_enclose_memory
+ final int num = env.addMemEntry();
en.regNum = num;
node = en;
}
fetchToken();
- Node target = parseSubExp(term);
+ final Node target = parseSubExp(term);
if (node.getType() == NodeType.ANCHOR) {
- AnchorNode an = (AnchorNode) node;
+ final AnchorNode an = (AnchorNode) node;
an.setTarget(target);
} else {
- EncloseNode en = (EncloseNode)node;
+ final EncloseNode en = (EncloseNode)node;
en.setTarget(target);
if (en.type == EncloseType.MEMORY) {
/* Don't move this to previous of parse_subexp() */
@@ -442,8 +449,11 @@ class Parser extends Lexer {
return node; // ??
}
- private Node parseExp(TokenType term) {
- if (token.type == term) return StringNode.EMPTY; // goto end_of_token
+ private Node parseExp(final TokenType term) {
+ if (token.type == term)
+ {
+ return StringNode.EMPTY; // goto end_of_token
+ }
Node node = null;
boolean group = false;
@@ -458,11 +468,11 @@ class Parser extends Lexer {
if (returnCode == 1) {
group = true;
} else if (returnCode == 2) { /* option only */
- int prev = env.option;
- EncloseNode en = (EncloseNode)node;
+ final int prev = env.option;
+ final EncloseNode en = (EncloseNode)node;
env.option = en.option;
fetchToken();
- Node target = parseSubExp(term);
+ final Node target = parseSubExp(term);
env.option = prev;
en.setTarget(target);
return node;
@@ -474,16 +484,15 @@ class Parser extends Lexer {
}
if (token.escaped) {
return parseExpTkRawByte(group); // goto tk_raw_byte
- } else {
- return parseExpTkByte(group); // goto tk_byte
}
+ return parseExpTkByte(group); // goto tk_byte
case STRING:
return parseExpTkByte(group); // tk_byte:
case RAW_BYTE:
return parseExpTkRawByte(group); // tk_raw_byte:
case CODE_POINT:
- char[] buf = new char[] {(char)token.getCode()};
+ final char[] buf = new char[] {(char)token.getCode()};
// #ifdef NUMBERED_CHAR_IS_NOT_CASE_AMBIG ... // setRaw() #else
node = new StringNode(buf, 0, 1);
break;
@@ -494,9 +503,11 @@ class Parser extends Lexer {
case CharacterType.S:
case CharacterType.W:
if (Config.NON_UNICODE_SDW) {
- CClassNode cc = new CClassNode();
+ final CClassNode cc = new CClassNode();
cc.addCType(token.getPropCType(), false, env, this);
- if (token.getPropNot()) cc.setNot();
+ if (token.getPropNot()) {
+ cc.setNot();
+ }
node = cc;
}
break;
@@ -505,9 +516,11 @@ class Parser extends Lexer {
case CharacterType.DIGIT:
case CharacterType.XDIGIT:
// #ifdef USE_SHARED_CCLASS_TABLE ... #endif
- CClassNode ccn = new CClassNode();
+ final CClassNode ccn = new CClassNode();
ccn.addCType(token.getPropCType(), false, env, this);
- if (token.getPropNot()) ccn.setNot();
+ if (token.getPropNot()) {
+ ccn.setNot();
+ }
node = ccn;
break;
@@ -518,10 +531,10 @@ class Parser extends Lexer {
break;
case CC_CC_OPEN:
- CClassNode cc = parseCharClass();
+ final CClassNode cc = parseCharClass();
node = cc;
if (isIgnoreCase(env.option)) {
- ApplyCaseFoldArg arg = new ApplyCaseFoldArg(env, cc);
+ final ApplyCaseFoldArg arg = new ApplyCaseFoldArg(env, cc);
EncodingHelper.applyAllCaseFold(env.caseFoldFlag, ApplyCaseFold.INSTANCE, arg);
if (arg.altRoot != null) {
@@ -536,13 +549,13 @@ class Parser extends Lexer {
case ANYCHAR_ANYTIME:
node = new AnyCharNode();
- QuantifierNode qn = new QuantifierNode(0, QuantifierNode.REPEAT_INFINITE, false);
+ final QuantifierNode qn = new QuantifierNode(0, QuantifierNode.REPEAT_INFINITE, false);
qn.setTarget(node);
node = qn;
break;
case BACKREF:
- int backRef = token.getBackrefRef();
+ final int backRef = token.getBackrefRef();
node = new BackRefNode(backRef, env);
break;
@@ -555,9 +568,8 @@ class Parser extends Lexer {
if (syntax.contextIndepRepeatOps()) {
if (syntax.contextInvalidRepeatOps()) {
throw new SyntaxException(ERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED);
- } else {
- node = StringNode.EMPTY; // node_new_empty
}
+ node = StringNode.EMPTY; // node_new_empty
} else {
return parseExpTkByte(group); // goto tk_byte
}
@@ -574,11 +586,13 @@ class Parser extends Lexer {
return parseExpRepeat(node, group); // repeat:
}
- private Node parseExpTkByte(boolean group) {
- StringNode node = new StringNode(chars, token.backP, p); // tk_byte:
+ private Node parseExpTkByte(final boolean group) {
+ final StringNode node = new StringNode(chars, token.backP, p); // tk_byte:
while (true) {
fetchToken();
- if (token.type != TokenType.STRING) break;
+ if (token.type != TokenType.STRING) {
+ break;
+ }
if (token.backP == node.end) {
node.end = p; // non escaped character, remain shared, just increase shared range
@@ -590,13 +604,13 @@ class Parser extends Lexer {
return parseExpRepeat(node, group); // string_end:, goto repeat
}
- private Node parseExpTkRawByte(boolean group) {
+ private Node parseExpTkRawByte(final boolean group) {
// tk_raw_byte:
// important: we don't use 0xff mask here neither in the compiler
// (in the template string) so we won't have to mask target
// strings when comparing against them in the matcher
- StringNode node = new StringNode((char)token.getC());
+ final StringNode node = new StringNode((char)token.getC());
node.setRaw();
fetchToken();
@@ -605,22 +619,23 @@ class Parser extends Lexer {
return parseExpRepeat(node, group);
}
- private Node parseExpRepeat(Node target, boolean group) {
+ private Node parseExpRepeat(final Node targetp, final boolean group) {
+ Node target = targetp;
while (token.type == TokenType.OP_REPEAT || token.type == TokenType.INTERVAL) { // repeat:
if (target.isInvalidQuantifier()) {
throw new SyntaxException(ERR_TARGET_OF_REPEAT_OPERATOR_INVALID);
}
- QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
+ final QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
token.getRepeatUpper(),
token.type == TokenType.INTERVAL);
qtfr.greedy = token.getRepeatGreedy();
- int ret = qtfr.setQuantifier(target, group, env, chars, getBegin(), getEnd());
+ final int ret = qtfr.setQuantifier(target, group, env, chars, getBegin(), getEnd());
Node qn = qtfr;
if (token.getRepeatPossessive()) {
- EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
+ final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
en.setTarget(qn);
qn = en;
}
@@ -629,7 +644,7 @@ class Parser extends Lexer {
target = qn;
} else if (ret == 2) { /* split case: /abc+/ */
target = ConsAltNode.newListNode(target, null);
- ConsAltNode tmp = ((ConsAltNode)target).setCdr(ConsAltNode.newListNode(qn, null));
+ final ConsAltNode tmp = ((ConsAltNode)target).setCdr(ConsAltNode.newListNode(qn, null));
fetchToken();
return parseExpRepeatForCar(target, tmp, group);
@@ -639,22 +654,22 @@ class Parser extends Lexer {
return target;
}
- private Node parseExpRepeatForCar(Node top, ConsAltNode target, boolean group) {
+ private Node parseExpRepeatForCar(final Node top, final ConsAltNode target, final boolean group) {
while (token.type == TokenType.OP_REPEAT || token.type == TokenType.INTERVAL) { // repeat:
if (target.car.isInvalidQuantifier()) {
throw new SyntaxException(ERR_TARGET_OF_REPEAT_OPERATOR_INVALID);
}
- QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
+ final QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
token.getRepeatUpper(),
token.type == TokenType.INTERVAL);
qtfr.greedy = token.getRepeatGreedy();
- int ret = qtfr.setQuantifier(target.car, group, env, chars, getBegin(), getEnd());
+ final int ret = qtfr.setQuantifier(target.car, group, env, chars, getBegin(), getEnd());
Node qn = qtfr;
if (token.getRepeatPossessive()) {
- EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
+ final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
en.setTarget(qn);
qn = en;
}
@@ -669,39 +684,40 @@ class Parser extends Lexer {
return top;
}
- private Node parseBranch(TokenType term) {
+ private Node parseBranch(final TokenType term) {
Node node = parseExp(term);
if (token.type == TokenType.EOT || token.type == term || token.type == TokenType.ALT) {
return node;
- } else {
- ConsAltNode top = ConsAltNode.newListNode(node, null);
- ConsAltNode t = top;
-
- while (token.type != TokenType.EOT && token.type != term && token.type != TokenType.ALT) {
- node = parseExp(term);
- if (node.getType() == NodeType.LIST) {
- t.setCdr((ConsAltNode)node);
- while (((ConsAltNode)node).cdr != null ) node = ((ConsAltNode)node).cdr;
-
- t = ((ConsAltNode)node);
- } else {
- t.setCdr(ConsAltNode.newListNode(node, null));
- t = t.cdr;
+ }
+ final ConsAltNode top = ConsAltNode.newListNode(node, null);
+ ConsAltNode t = top;
+
+ while (token.type != TokenType.EOT && token.type != term && token.type != TokenType.ALT) {
+ node = parseExp(term);
+ if (node.getType() == NodeType.LIST) {
+ t.setCdr((ConsAltNode)node);
+ while (((ConsAltNode)node).cdr != null ) {
+ node = ((ConsAltNode)node).cdr;
}
+
+ t = ((ConsAltNode)node);
+ } else {
+ t.setCdr(ConsAltNode.newListNode(node, null));
+ t = t.cdr;
}
- return top;
}
+ return top;
}
/* term_tok: TK_EOT or TK_SUBEXP_CLOSE */
- private Node parseSubExp(TokenType term) {
+ private Node parseSubExp(final TokenType term) {
Node node = parseBranch(term);
if (token.type == term) {
return node;
} else if (token.type == TokenType.ALT) {
- ConsAltNode top = ConsAltNode.newAltNode(node, null);
+ final ConsAltNode top = ConsAltNode.newAltNode(node, null);
ConsAltNode t = top;
while (token.type == TokenType.ALT) {
fetchToken();
@@ -711,7 +727,9 @@ class Parser extends Lexer {
t = t.cdr;
}
- if (token.type != term) parseSubExpError(term);
+ if (token.type != term) {
+ parseSubExpError(term);
+ }
return top;
} else {
parseSubExpError(term);
@@ -719,12 +737,11 @@ class Parser extends Lexer {
}
}
- private void parseSubExpError(TokenType term) {
+ private static void parseSubExpError(final TokenType term) {
if (term == TokenType.SUBEXP_CLOSE) {
throw new SyntaxException(ERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS);
- } else {
- throw new InternalException(ERR_PARSER_BUG);
}
+ throw new InternalException(ERR_PARSER_BUG);
}
private Node parseRegexp() {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
index 91117d1d..bd335bb7 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
@@ -24,6 +24,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;
+@SuppressWarnings("javadoc")
public final class Regex implements RegexState {
int[] code; /* compiled pattern */
@@ -72,42 +73,43 @@ public final class Regex implements RegexState {
char[][] templates;
int templateNum;
- public Regex(CharSequence cs) {
+ public Regex(final CharSequence cs) {
this(cs.toString());
}
- public Regex(String str) {
+ public Regex(final String str) {
this(str.toCharArray(), 0, str.length(), 0);
}
- public Regex(char[] chars) {
+ public Regex(final char[] chars) {
this(chars, 0, chars.length, 0);
}
- public Regex(char[] chars, int p, int end) {
+ public Regex(final char[] chars, final int p, final int end) {
this(chars, p, end, 0);
}
- public Regex(char[] chars, int p, int end, int option) {
+ public Regex(final char[] chars, final int p, final int end, final int option) {
this(chars, p, end, option, Syntax.RUBY, WarnCallback.DEFAULT);
}
// onig_new
- public Regex(char[] chars, int p, int end, int option, Syntax syntax) {
+ public Regex(final char[] chars, final int p, final int end, final int option, final Syntax syntax) {
this(chars, p, end, option, Config.ENC_CASE_FOLD_DEFAULT, syntax, WarnCallback.DEFAULT);
}
- public Regex(char[]chars, int p, int end, int option, WarnCallback warnings) {
+ public Regex(final char[]chars, final int p, final int end, final int option, final WarnCallback warnings) {
this(chars, p, end, option, Syntax.RUBY, warnings);
}
// onig_new
- public Regex(char[] chars, int p, int end, int option, Syntax syntax, WarnCallback warnings) {
+ public Regex(final char[] chars, final int p, final int end, final int option, final Syntax syntax, final WarnCallback warnings) {
this(chars, p, end, option, Config.ENC_CASE_FOLD_DEFAULT, syntax, warnings);
}
// onig_alloc_init
- public Regex(char[] chars, int p, int end, int option, int caseFoldFlag, Syntax syntax, WarnCallback warnings) {
+ public Regex(final char[] chars, final int p, final int end, final int optionp, final int caseFoldFlag, final Syntax syntax, final WarnCallback warnings) {
+ int option = optionp;
if ((option & (Option.DONT_CAPTURE_GROUP | Option.CAPTURE_GROUP)) ==
(Option.DONT_CAPTURE_GROUP | Option.CAPTURE_GROUP)) {
@@ -140,11 +142,11 @@ public final class Regex implements RegexState {
return factory;
}
- public Matcher matcher(char[] chars) {
+ public Matcher matcher(final char[] chars) {
return matcher(chars, 0, chars.length);
}
- public Matcher matcher(char[] chars, int p, int end) {
+ public Matcher matcher(final char[] chars, final int p, final int end) {
MatcherFactory matcherFactory = factory;
if (matcherFactory == null) {
matcherFactory = compile();
@@ -162,26 +164,40 @@ public final class Regex implements RegexState {
/* set skip map for Boyer-Moor search */
void setupBMSkipMap() {
- char[] chars = exact;
- int p = exactP;
- int end = exactEnd;
- int len = end - p;
+ final char[] chars = exact;
+ final int p = exactP;
+ final int end = exactEnd;
+ final int len = end - p;
if (len < Config.CHAR_TABLE_SIZE) {
// map/skip
- if (map == null) map = new byte[Config.CHAR_TABLE_SIZE];
+ if (map == null) {
+ map = new byte[Config.CHAR_TABLE_SIZE];
+ }
- for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) map[i] = (byte)len;
- for (int i=0; i<len-1; i++) map[chars[p + i] & 0xff] = (byte)(len - 1 -i); // oxff ??
+ for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) {
+ map[i] = (byte)len;
+ }
+ for (int i=0; i<len-1; i++)
+ {
+ map[chars[p + i] & 0xff] = (byte)(len - 1 -i); // oxff ??
+ }
} else {
- if (intMap == null) intMap = new int[Config.CHAR_TABLE_SIZE];
+ if (intMap == null) {
+ intMap = new int[Config.CHAR_TABLE_SIZE];
+ }
- for (int i=0; i<len-1; i++) intMap[chars[p + i] & 0xff] = len - 1 - i; // oxff ??
+ for (int i=0; i<len-1; i++)
+ {
+ intMap[chars[p + i] & 0xff] = len - 1 - i; // oxff ??
+ }
}
}
- void setExactInfo(OptExactInfo e) {
- if (e.length == 0) return;
+ void setExactInfo(final OptExactInfo e) {
+ if (e.length == 0) {
+ return;
+ }
// shall we copy that ?
exact = e.chars;
@@ -207,7 +223,7 @@ public final class Regex implements RegexState {
}
}
- void setOptimizeMapInfo(OptMapInfo m) {
+ void setOptimizeMapInfo(final OptMapInfo m) {
map = m.map;
searchAlgorithm = SearchAlgorithm.MAP;
@@ -219,7 +235,7 @@ public final class Regex implements RegexState {
}
}
- void setSubAnchor(OptAnchorInfo anc) {
+ void setSubAnchor(final OptAnchorInfo anc) {
subAnchor |= anc.leftAnchor & AnchorType.BEGIN_LINE;
subAnchor |= anc.rightAnchor & AnchorType.END_LINE;
}
@@ -236,7 +252,7 @@ public final class Regex implements RegexState {
}
public String optimizeInfoToString() {
- StringBuilder s = new StringBuilder();
+ final StringBuilder s = new StringBuilder();
s.append("optimize: ").append(searchAlgorithm.getName()).append("\n");
s.append(" anchor: ").append(OptAnchorInfo.anchorToString(anchor));
@@ -257,7 +273,11 @@ public final class Regex implements RegexState {
s.append("exact: [").append(exact, exactP, exactEnd - exactP).append("]: length: ").append(exactEnd - exactP).append("\n");
} else if (searchAlgorithm == SearchAlgorithm.MAP) {
int n=0;
- for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) if (map[i] != 0) n++;
+ for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) {
+ if (map[i] != 0) {
+ n++;
+ }
+ }
s.append("map: n = ").append(n).append("\n");
if (n > 0) {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
index 9281954c..32db18e1 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public final class Region {
static final int REGION_NOTPOS = -1;
@@ -26,7 +27,7 @@ public final class Region {
public final int[]beg;
public final int[]end;
- public Region(int num) {
+ public Region(final int num) {
this.numRegs = num;
this.beg = new int[num];
this.end = new int[num];
@@ -34,9 +35,11 @@ public final class Region {
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append("Region: \n");
- for (int i=0; i<beg.length; i++) sb.append(" " + i + ": (" + beg[i] + "-" + end[i] + ")");
+ for (int i=0; i<beg.length; i++) {
+ sb.append(" " + i + ": (" + beg[i] + "-" + end[i] + ")");
+ }
return sb.toString();
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
index adecb1d0..48f5ce0b 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
@@ -20,11 +20,11 @@
package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsClear;
-
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
+@SuppressWarnings("javadoc")
public final class ScanEnvironment {
private static final int SCANENV_MEMNODES_SIZE = 8;
@@ -44,7 +44,7 @@ public final class ScanEnvironment {
public Node memNodes[];
- public ScanEnvironment(Regex regex, Syntax syntax) {
+ public ScanEnvironment(final Regex regex, final Syntax syntax) {
this.reg = regex;
option = regex.options;
caseFoldFlag = regex.caseFoldFlag;
@@ -65,7 +65,7 @@ public final class ScanEnvironment {
if (numMem++ == 0) {
memNodes = new Node[SCANENV_MEMNODES_SIZE];
} else if (numMem >= memNodes.length) {
- Node[]tmp = new Node[memNodes.length << 1];
+ final Node[]tmp = new Node[memNodes.length << 1];
System.arraycopy(memNodes, 0, tmp, 0, memNodes.length);
memNodes = tmp;
}
@@ -73,7 +73,7 @@ public final class ScanEnvironment {
return numMem;
}
- public void setMemNode(int num, Node node) {
+ public void setMemNode(final int num, final Node node) {
if (numMem >= num) {
memNodes[num] = node;
} else {
@@ -81,7 +81,7 @@ public final class ScanEnvironment {
}
}
- public int convertBackslashValue(int c) {
+ public int convertBackslashValue(final int c) {
if (syntax.opEscControlChars()) {
switch (c) {
case 'n': return '\n';
@@ -92,7 +92,10 @@ public final class ScanEnvironment {
case 'b': return '\010';
case 'e': return '\033';
case 'v':
- if (syntax.op2EscVVtab()) return 11; // ???
+ if (syntax.op2EscVVtab())
+ {
+ return 11; // ???
+ }
break;
default:
break;
@@ -101,7 +104,7 @@ public final class ScanEnvironment {
return c;
}
- void ccEscWarn(String s) {
+ void ccEscWarn(final String s) {
if (Config.USE_WARN) {
if (syntax.warnCCOpNotEscaped() && syntax.backSlashEscapeInCC()) {
reg.warnings.warn("character class has '" + s + "' without escape");
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
index ad4aaaf6..6ae186c8 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
@@ -36,7 +36,7 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
private final static int INT_SIGN_BIT = 1 << 31;
- protected ScannerSupport(char[] chars, int p, int end) {
+ protected ScannerSupport(final char[] chars, final int p, final int end) {
this.chars = chars;
this.begin = p;
this.end = end;
@@ -53,14 +53,16 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
}
protected final int scanUnsignedNumber() {
- int last = c;
+ final int last = c;
int num = 0; // long ???
while(left()) {
fetch();
if (Character.isDigit(c)) {
- int onum = num;
+ final int onum = num;
num = num * 10 + EncodingHelper.digitVal(c);
- if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
+ if (((onum ^ num) & INT_SIGN_BIT) != 0) {
+ return -1;
+ }
} else {
unfetch();
break;
@@ -70,16 +72,19 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
return num;
}
- protected final int scanUnsignedHexadecimalNumber(int maxLength) {
- int last = c;
+ protected final int scanUnsignedHexadecimalNumber(final int maxLength) {
+ final int last = c;
int num = 0;
- while(left() && maxLength-- != 0) {
+ int ml = maxLength;
+ while(left() && ml-- != 0) {
fetch();
if (EncodingHelper.isXDigit(c)) {
- int onum = num;
- int val = EncodingHelper.xdigitVal(c);
+ final int onum = num;
+ final int val = EncodingHelper.xdigitVal(c);
num = (num << 4) + val;
- if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
+ if (((onum ^ num) & INT_SIGN_BIT) != 0) {
+ return -1;
+ }
} else {
unfetch();
break;
@@ -89,16 +94,19 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
return num;
}
- protected final int scanUnsignedOctalNumber(int maxLength) {
- int last = c;
+ protected final int scanUnsignedOctalNumber(final int maxLength) {
+ final int last = c;
int num = 0;
- while(left() && maxLength-- != 0) {
+ int ml = maxLength;
+ while(left() && ml-- != 0) {
fetch();
if (Character.isDigit(c) && c < '8') {
- int onum = num;
- int val = EncodingHelper.odigitVal(c);
+ final int onum = num;
+ final int val = EncodingHelper.odigitVal(c);
num = (num << 3) + val;
- if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
+ if (((onum ^ num) & INT_SIGN_BIT) != 0) {
+ return -1;
+ }
} else {
unfetch();
break;
@@ -144,8 +152,8 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
return p < stop ? chars[p] : 0;
}
- protected final boolean peekIs(int c) {
- return peek() == c;
+ protected final boolean peekIs(final int ch) {
+ return peek() == ch;
}
protected final boolean left() {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java b/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
index 5b2eac97..7fea303b 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public abstract class SearchAlgorithm {
public abstract String getName();
@@ -34,12 +35,12 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
+ public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
return textP;
}
@Override
- public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
+ public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
return textP;
}
@@ -53,16 +54,18 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
int end = textEnd;
end -= targetEnd - targetP - 1;
- if (end > textRange) end = textRange;
+ if (end > textRange) {
+ end = textRange;
+ }
int s = textP;
@@ -71,11 +74,15 @@ public abstract class SearchAlgorithm {
int p = s + 1;
int t = targetP + 1;
while (t < targetEnd) {
- if (target[t] != text[p++]) break;
+ if (target[t] != text[p++]) {
+ break;
+ }
t++;
}
- if (t == targetEnd) return s;
+ if (t == targetEnd) {
+ return s;
+ }
}
s++;
}
@@ -84,10 +91,10 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
int s = textEnd;
s -= targetEnd - targetP;
@@ -101,10 +108,14 @@ public abstract class SearchAlgorithm {
int p = s + 1;
int t = targetP + 1;
while (t < targetEnd) {
- if (target[t] != text[p++]) break;
+ if (target[t] != text[p++]) {
+ break;
+ }
t++;
}
- if (t == targetEnd) return s;
+ if (t == targetEnd) {
+ return s;
+ }
}
// s = enc.prevCharHead or s = s <= adjustText ? -1 : s - 1;
s--;
@@ -114,10 +125,8 @@ public abstract class SearchAlgorithm {
};
public static final class SLOW_IC extends SearchAlgorithm {
- private final int caseFoldFlag;
-
- public SLOW_IC(Regex regex) {
- this.caseFoldFlag = regex.caseFoldFlag;
+ public SLOW_IC(final Regex regex) {
+ //empty
}
@Override
@@ -126,29 +135,33 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
int end = textEnd;
end -= targetEnd - targetP - 1;
- if (end > textRange) end = textRange;
+ if (end > textRange) {
+ end = textRange;
+ }
int s = textP;
while (s < end) {
- if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) return s;
+ if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) {
+ return s;
+ }
s++;
}
return -1;
}
@Override
- public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
int s = textEnd;
s -= targetEnd - targetP;
@@ -158,17 +171,21 @@ public abstract class SearchAlgorithm {
}
while (s >= textP) {
- if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) return s;
+ if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) {
+ return s;
+ }
s = EncodingHelper.prevCharHead(adjustText, s);
}
return -1;
}
- private boolean lowerCaseMatch(char[] t, int tP, int tEnd,
- char[] chars, int p, int end) {
+ private static boolean lowerCaseMatch(final char[] t, final int tPp, final int tEnd,
+ final char[] chars, final int pp, final int end) {
- while (tP < tEnd) {
- if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) return false;
+ for (int tP = tPp, p = pp; tP < tEnd; ) {
+ if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) {
+ return false;
+ }
}
return true;
}
@@ -182,15 +199,17 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
int end = textRange + (targetEnd - targetP) - 1;
- if (end > textEnd) end = textEnd;
+ if (end > textEnd) {
+ end = textEnd;
+ }
- int tail = targetEnd - 1;
+ final int tail = targetEnd - 1;
int s = textP + (targetEnd - targetP) - 1;
if (regex.intMap == null) {
@@ -199,7 +218,9 @@ public abstract class SearchAlgorithm {
int t = tail;
while (text[p] == target[t]) {
- if (t == targetP) return p;
+ if (t == targetP) {
+ return p;
+ }
p--; t--;
}
@@ -211,7 +232,9 @@ public abstract class SearchAlgorithm {
int t = tail;
while (text[p] == target[t]) {
- if (t == targetP) return p;
+ if (t == targetP) {
+ return p;
+ }
p--; t--;
}
@@ -224,10 +247,10 @@ public abstract class SearchAlgorithm {
private static final int BM_BACKWARD_SEARCH_LENGTH_THRESHOLD = 100;
@Override
- public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
- char[] target = regex.exact;
- int targetP = regex.exactP;
- int targetEnd = regex.exactEnd;
+ public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+ final char[] target = regex.exact;
+ final int targetP = regex.exactP;
+ final int targetEnd = regex.exactEnd;
if (regex.intMapBackward == null) {
if (s_ - range_ < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD) {
@@ -249,7 +272,9 @@ public abstract class SearchAlgorithm {
while (t < targetEnd && text[p] == target[t]) {
p++; t++;
}
- if (t == targetEnd) return s;
+ if (t == targetEnd) {
+ return s;
+ }
s -= regex.intMapBackward[text[s] & 0xff];
}
@@ -257,7 +282,7 @@ public abstract class SearchAlgorithm {
}
- private void setBmBackwardSkip(Regex regex, char[] chars, int p, int end) {
+ private void setBmBackwardSkip(final Regex regex, final char[] chars, final int p, final int end) {
int[] skip;
if (regex.intMapBackward == null) {
skip = new int[Config.CHAR_TABLE_SIZE];
@@ -266,10 +291,14 @@ public abstract class SearchAlgorithm {
skip = regex.intMapBackward;
}
- int len = end - p;
+ final int len = end - p;
- for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) skip[i] = len;
- for (int i=len-1; i>0; i--) skip[chars[i] & 0xff] = i;
+ for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) {
+ skip[i] = len;
+ }
+ for (int i=len-1; i>0; i--) {
+ skip[chars[i] & 0xff] = i;
+ }
}
};
@@ -281,25 +310,31 @@ public abstract class SearchAlgorithm {
}
@Override
- public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
- byte[] map = regex.map;
+ public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+ final byte[] map = regex.map;
int s = textP;
while (s < textRange) {
- if (text[s] > 0xff || map[text[s]] != 0) return s;
+ if (text[s] > 0xff || map[text[s]] != 0) {
+ return s;
+ }
s++;
}
return -1;
}
@Override
- public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
- byte[] map = regex.map;
+ public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+ final byte[] map = regex.map;
int s = textStart;
- if (s >= textEnd) s = textEnd - 1;
+ if (s >= textEnd) {
+ s = textEnd - 1;
+ }
while (s >= textP) {
- if (text[s] > 0xff || map[text[s]] != 0) return s;
+ if (text[s] > 0xff || map[text[s]] != 0) {
+ return s;
+ }
s--;
}
return -1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java b/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
index 9161336a..36a65d62 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
@@ -25,28 +25,28 @@ final class StackEntry {
// first union member
/* byte code position */
- void setStatePCode(int pcode) {
+ void setStatePCode(final int pcode) {
E1 = pcode;
}
int getStatePCode() {
return E1;
}
/* string position */
- void setStatePStr(int pstr) {
+ void setStatePStr(final int pstr) {
E2 = pstr;
}
int getStatePStr() {
return E2;
}
/* previous char position of pstr */
- void setStatePStrPrev(int pstrPrev) {
+ void setStatePStrPrev(final int pstrPrev) {
E3 = pstrPrev;
}
int getStatePStrPrev() {
return E3;
}
- void setStateCheck(int check) {
+ void setStateCheck(final int check) {
E4 = check;
}
int getStateCheck() {
@@ -55,7 +55,7 @@ final class StackEntry {
// second union member
/* for OP_REPEAT_INC, OP_REPEAT_INC_NG */
- void setRepeatCount(int count) {
+ void setRepeatCount(final int count) {
E1 = count;
}
int getRepeatCount() {
@@ -68,14 +68,14 @@ final class StackEntry {
E1++;
}
/* byte code position (head of repeated target) */
- void setRepeatPCode(int pcode) {
+ void setRepeatPCode(final int pcode) {
E2 = pcode;
}
int getRepeatPCode() {
return E2;
}
/* repeat id */
- void setRepeatNum(int num) {
+ void setRepeatNum(final int num) {
E3 = num;
}
int getRepeatNum() {
@@ -84,7 +84,7 @@ final class StackEntry {
// third union member
/* index of stack */ /*int repeat_inc struct*/
- void setSi(int si) {
+ void setSi(final int si) {
E1 = si;
}
int getSi() {
@@ -93,14 +93,14 @@ final class StackEntry {
// fourth union member
/* memory num */
- void setMemNum(int num) {
+ void setMemNum(final int num) {
E1 = num;
}
int getMemNum() {
return E1;
}
/* start/end position */
- void setMemPstr(int pstr) {
+ void setMemPstr(final int pstr) {
E2 = pstr;
}
int getMemPStr() {
@@ -109,14 +109,14 @@ final class StackEntry {
/* Following information is set, if this stack type is MEM-START */
/* prev. info (for backtrack "(...)*" ) */
- void setMemStart(int start) {
+ void setMemStart(final int start) {
E3 = start;
}
int getMemStart() {
return E3;
}
/* prev. info (for backtrack "(...)*" ) */
- void setMemEnd(int end) {
+ void setMemEnd(final int end) {
E4 = end;
}
int getMemEnd() {
@@ -125,14 +125,14 @@ final class StackEntry {
// fifth union member
/* null check id */
- void setNullCheckNum(int num) {
+ void setNullCheckNum(final int num) {
E1 = num;
}
int getNullCheckNum() {
return E1;
}
/* start position */
- void setNullCheckPStr(int pstr) {
+ void setNullCheckPStr(final int pstr) {
E2 = pstr;
}
int getNullCheckPStr() {
@@ -141,21 +141,21 @@ final class StackEntry {
// sixth union member
/* byte code position */
- void setCallFrameRetAddr(int addr) {
+ void setCallFrameRetAddr(final int addr) {
E1 = addr;
}
int getCallFrameRetAddr() {
return E1;
}
/* null check id */
- void setCallFrameNum(int num) {
+ void setCallFrameNum(final int num) {
E2 = num;
}
int getCallFrameNum() {
return E2;
}
/* string position */
- void setCallFramePStr(int pstr) {
+ void setCallFramePStr(final int pstr) {
E3 = pstr;
}
int getCallFramePStr() {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
index cacf3182..fc498c45 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
@@ -20,9 +20,7 @@
package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
-
import java.lang.ref.WeakReference;
-
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
@@ -35,11 +33,11 @@ abstract class StackMachine extends Matcher implements StackType {
protected final int[]repeatStk;
protected final int memStartStk, memEndStk;
- protected StackMachine(Regex regex, char[] chars, int p , int end) {
+ protected StackMachine(final Regex regex, final char[] chars, final int p , final int end) {
super(regex, chars, p, end);
this.stack = regex.stackNeeded ? fetchStack() : null;
- int n = regex.numRepeat + (regex.numMem << 1);
+ final int n = regex.numRepeat + (regex.numMem << 1);
this.repeatStk = n > 0 ? new int[n] : null;
memStartStk = regex.numRepeat - 1;
@@ -49,25 +47,27 @@ abstract class StackMachine extends Matcher implements StackType {
}
private static StackEntry[] allocateStack() {
- StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE];
+ final StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE];
stack[0] = new StackEntry();
return stack;
}
private void doubleStack() {
- StackEntry[] newStack = new StackEntry[stack.length << 1];
+ final StackEntry[] newStack = new StackEntry[stack.length << 1];
System.arraycopy(stack, 0, newStack, 0, stack.length);
stack = newStack;
}
static final ThreadLocal<WeakReference<StackEntry[]>> stacks
= new ThreadLocal<WeakReference<StackEntry[]>>() {
+ @SuppressWarnings("unused")
@Override
protected WeakReference<StackEntry[]> initialValue() {
return new WeakReference<StackEntry[]>(allocateStack());
}
};
+ @SuppressWarnings("unused")
private static StackEntry[] fetchStack() {
WeakReference<StackEntry[]> ref = stacks.get();
StackEntry[] stack = ref.get();
@@ -79,7 +79,9 @@ abstract class StackMachine extends Matcher implements StackType {
}
protected final void init() {
- if (stack != null) pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */
+ if (stack != null) {
+ pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */
+ }
if (repeatStk != null) {
for (int i=1; i<=regex.numMem; i++) {
repeatStk[i + memStartStk] = repeatStk[i + memEndStk] = INVALID_INDEX;
@@ -88,19 +90,23 @@ abstract class StackMachine extends Matcher implements StackType {
}
protected final StackEntry ensure1() {
- if (stk >= stack.length) doubleStack();
+ if (stk >= stack.length) {
+ doubleStack();
+ }
StackEntry e = stack[stk];
- if (e == null) stack[stk] = e = new StackEntry();
+ if (e == null) {
+ stack[stk] = e = new StackEntry();
+ }
return e;
}
- protected final void pushType(int type) {
+ protected final void pushType(final int type) {
ensure1().type = type;
stk++;
}
- private void push(int type, int pat, int s, int prev) {
- StackEntry e = ensure1();
+ private void push(final int type, final int pat, final int s, final int prev) {
+ final StackEntry e = ensure1();
e.type = type;
e.setStatePCode(pat);
e.setStatePStr(s);
@@ -108,22 +114,22 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
- protected final void pushEnsured(int type, int pat) {
- StackEntry e = stack[stk];
+ protected final void pushEnsured(final int type, final int pat) {
+ final StackEntry e = stack[stk];
e.type = type;
e.setStatePCode(pat);
stk++;
}
- protected final void pushAlt(int pat, int s, int prev) {
+ protected final void pushAlt(final int pat, final int s, final int prev) {
push(ALT, pat, s, prev);
}
- protected final void pushPos(int s, int prev) {
+ protected final void pushPos(final int s, final int prev) {
push(POS, -1 /*NULL_UCHARP*/, s, prev);
}
- protected final void pushPosNot(int pat, int s, int prev) {
+ protected final void pushPosNot(final int pat, final int s, final int prev) {
push(POS_NOT, pat, s, prev);
}
@@ -131,12 +137,12 @@ abstract class StackMachine extends Matcher implements StackType {
pushType(STOP_BT);
}
- protected final void pushLookBehindNot(int pat, int s, int sprev) {
+ protected final void pushLookBehindNot(final int pat, final int s, final int sprev) {
push(LOOK_BEHIND_NOT, pat, s, sprev);
}
- protected final void pushRepeat(int id, int pat) {
- StackEntry e = ensure1();
+ protected final void pushRepeat(final int id, final int pat) {
+ final StackEntry e = ensure1();
e.type = REPEAT;
e.setRepeatNum(id);
e.setRepeatPCode(pat);
@@ -144,15 +150,15 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
- protected final void pushRepeatInc(int sindex) {
- StackEntry e = ensure1();
+ protected final void pushRepeatInc(final int sindex) {
+ final StackEntry e = ensure1();
e.type = REPEAT_INC;
e.setSi(sindex);
stk++;
}
- protected final void pushMemStart(int mnum, int s) {
- StackEntry e = ensure1();
+ protected final void pushMemStart(final int mnum, final int s) {
+ final StackEntry e = ensure1();
e.type = MEM_START;
e.setMemNum(mnum);
e.setMemPstr(s);
@@ -163,8 +169,8 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
- protected final void pushMemEnd(int mnum, int s) {
- StackEntry e = ensure1();
+ protected final void pushMemEnd(final int mnum, final int s) {
+ final StackEntry e = ensure1();
e.type = MEM_END;
e.setMemNum(mnum);
e.setMemPstr(s);
@@ -174,40 +180,42 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
- protected final void pushMemEndMark(int mnum) {
- StackEntry e = ensure1();
+ protected final void pushMemEndMark(final int mnum) {
+ final StackEntry e = ensure1();
e.type = MEM_END_MARK;
e.setMemNum(mnum);
stk++;
}
- protected final int getMemStart(int mnum) {
+ protected final int getMemStart(final int mnum) {
int level = 0;
int stkp = stk;
while (stkp > 0) {
stkp--;
- StackEntry e = stack[stkp];
+ final StackEntry e = stack[stkp];
if ((e.type & MASK_MEM_END_OR_MARK) != 0 && e.getMemNum() == mnum) {
level++;
} else if (e.type == MEM_START && e.getMemNum() == mnum) {
- if (level == 0) break;
+ if (level == 0) {
+ break;
+ }
level--;
}
}
return stkp;
}
- protected final void pushNullCheckStart(int cnum, int s) {
- StackEntry e = ensure1();
+ protected final void pushNullCheckStart(final int cnum, final int s) {
+ final StackEntry e = ensure1();
e.type = NULL_CHECK_START;
e.setNullCheckNum(cnum);
e.setNullCheckPStr(s);
stk++;
}
- protected final void pushNullCheckEnd(int cnum) {
- StackEntry e = ensure1();
+ protected final void pushNullCheckEnd(final int cnum) {
+ final StackEntry e = ensure1();
e.type = NULL_CHECK_END;
e.setNullCheckNum(cnum);
stk++;
@@ -233,7 +241,7 @@ abstract class StackMachine extends Matcher implements StackType {
private StackEntry popFree() {
while (true) {
- StackEntry e = stack[--stk];
+ final StackEntry e = stack[--stk];
if ((e.type & MASK_POP_USED) != 0) {
return e;
@@ -243,7 +251,7 @@ abstract class StackMachine extends Matcher implements StackType {
private StackEntry popMemStart() {
while (true) {
- StackEntry e = stack[--stk];
+ final StackEntry e = stack[--stk];
if ((e.type & MASK_POP_USED) != 0) {
return e;
@@ -256,7 +264,7 @@ abstract class StackMachine extends Matcher implements StackType {
private StackEntry popDefault() {
while (true) {
- StackEntry e = stack[--stk];
+ final StackEntry e = stack[--stk];
if ((e.type & MASK_POP_USED) != 0) {
return e;
@@ -277,7 +285,7 @@ abstract class StackMachine extends Matcher implements StackType {
protected final void popTilPosNot() {
while (true) {
stk--;
- StackEntry e = stack[stk];
+ final StackEntry e = stack[stk];
if (e.type == POS_NOT) {
break;
@@ -298,7 +306,7 @@ abstract class StackMachine extends Matcher implements StackType {
protected final void popTilLookBehindNot() {
while (true) {
stk--;
- StackEntry e = stack[stk];
+ final StackEntry e = stack[stk];
if (e.type == LOOK_BEHIND_NOT) {
break;
@@ -320,7 +328,7 @@ abstract class StackMachine extends Matcher implements StackType {
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if ((e.type & MASK_TO_VOID_TARGET) != 0) {
e.type = VOID;
} else if (e.type == POS) {
@@ -335,7 +343,7 @@ abstract class StackMachine extends Matcher implements StackType {
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if ((e.type & MASK_TO_VOID_TARGET) != 0) {
e.type = VOID;
@@ -347,11 +355,11 @@ abstract class StackMachine extends Matcher implements StackType {
}
// int for consistency with other null check routines
- protected final int nullCheck(int id, int s) {
+ protected final int nullCheck(final int id, final int s) {
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if (e.type == NULL_CHECK_START) {
if (e.getNullCheckNum() == id) {
@@ -361,20 +369,19 @@ abstract class StackMachine extends Matcher implements StackType {
}
}
- protected final int nullCheckRec(int id, int s) {
+ protected final int nullCheckRec(final int id, final int s) {
int level = 0;
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if (e.type == NULL_CHECK_START) {
if (e.getNullCheckNum() == id) {
if (level == 0) {
return e.getNullCheckPStr() == s ? 1 : 0;
- } else {
- level--;
}
+ level--;
}
} else if (e.type == NULL_CHECK_END) {
level++;
@@ -382,7 +389,7 @@ abstract class StackMachine extends Matcher implements StackType {
}
}
- protected final int nullCheckMemSt(int id, int s) {
+ protected final int nullCheckMemSt(final int id, final int s) {
int k = stk;
int isNull;
while (true) {
@@ -394,39 +401,38 @@ abstract class StackMachine extends Matcher implements StackType {
if (e.getNullCheckPStr() != s) {
isNull = 0;
break;
- } else {
- int endp;
- isNull = 1;
- while (k < stk) {
- if (e.type == MEM_START) {
- if (e.getMemEnd() == INVALID_INDEX) {
- isNull = 0;
- break;
- }
- if (bsAt(regex.btMemEnd, e.getMemNum())) {
- endp = stack[e.getMemEnd()].getMemPStr();
- } else {
- endp = e.getMemEnd();
- }
- if (stack[e.getMemStart()].getMemPStr() != endp) {
- isNull = 0;
- break;
- } else if (endp != s) {
- isNull = -1; /* empty, but position changed */
- }
+ }
+ int endp;
+ isNull = 1;
+ while (k < stk) {
+ if (e.type == MEM_START) {
+ if (e.getMemEnd() == INVALID_INDEX) {
+ isNull = 0;
+ break;
+ }
+ if (bsAt(regex.btMemEnd, e.getMemNum())) {
+ endp = stack[e.getMemEnd()].getMemPStr();
+ } else {
+ endp = e.getMemEnd();
+ }
+ if (stack[e.getMemStart()].getMemPStr() != endp) {
+ isNull = 0;
+ break;
+ } else if (endp != s) {
+ isNull = -1; /* empty, but position changed */
}
- k++;
- e = stack[k]; // !!
}
- break;
+ k++;
+ e = stack[k]; // !!
}
+ break;
}
}
}
return isNull;
}
- protected final int nullCheckMemStRec(int id, int s) {
+ protected final int nullCheckMemStRec(final int id, final int s) {
int level = 0;
int k = stk;
int isNull;
@@ -440,53 +446,55 @@ abstract class StackMachine extends Matcher implements StackType {
if (e.getNullCheckPStr() != s) {
isNull = 0;
break;
- } else {
- int endp;
- isNull = 1;
- while (k < stk) {
- if (e.type == MEM_START) {
- if (e.getMemEnd() == INVALID_INDEX) {
- isNull = 0;
- break;
- }
- if (bsAt(regex.btMemEnd, e.getMemNum())) {
- endp = stack[e.getMemEnd()].getMemPStr();
- } else {
- endp = e.getMemEnd();
- }
- if (stack[e.getMemStart()].getMemPStr() != endp) {
- isNull = 0;
- break;
- } else if (endp != s) {
- isNull = -1; /* empty, but position changed */
- }
+ }
+ int endp;
+ isNull = 1;
+ while (k < stk) {
+ if (e.type == MEM_START) {
+ if (e.getMemEnd() == INVALID_INDEX) {
+ isNull = 0;
+ break;
+ }
+ if (bsAt(regex.btMemEnd, e.getMemNum())) {
+ endp = stack[e.getMemEnd()].getMemPStr();
+ } else {
+ endp = e.getMemEnd();
+ }
+ if (stack[e.getMemStart()].getMemPStr() != endp) {
+ isNull = 0;
+ break;
+ } else if (endp != s) {
+ isNull = -1; /* empty, but position changed */
}
- k++;
- e = stack[k];
}
- break;
+ k++;
+ e = stack[k];
}
- } else {
- level--;
+ break;
}
+ level--;
}
} else if (e.type == NULL_CHECK_END) {
- if (e.getNullCheckNum() == id) level++;
+ if (e.getNullCheckNum() == id) {
+ level++;
+ }
}
}
return isNull;
}
- protected final int getRepeat(int id) {
+ protected final int getRepeat(final int id) {
int level = 0;
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if (e.type == REPEAT) {
if (level == 0) {
- if (e.getRepeatNum() == id) return k;
+ if (e.getRepeatNum() == id) {
+ return k;
+ }
}
} else if (e.type == CALL_FRAME) {
level--;
@@ -501,14 +509,13 @@ abstract class StackMachine extends Matcher implements StackType {
int k = stk;
while (true) {
k--;
- StackEntry e = stack[k];
+ final StackEntry e = stack[k];
if (e.type == CALL_FRAME) {
if (level == 0) {
return e.getCallFrameRetAddr();
- } else {
- level--;
}
+ level--;
} else if (e.type == RETURN) {
level++;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
index 518a416e..f58b85f5 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
@@ -20,17 +20,17 @@
package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar.INEFFECTIVE_META_CHAR;
-
import jdk.nashorn.internal.runtime.regexp.joni.constants.SyntaxProperties;
-public final class Syntax implements SyntaxProperties{
+@SuppressWarnings("javadoc")
+public final class Syntax implements SyntaxProperties {
private final int op;
private final int op2;
private final int behavior;
public final int options;
public final MetaCharTable metaCharTable;
- public Syntax(int op, int op2, int behavior, int options, MetaCharTable metaCharTable) {
+ public Syntax(final int op, final int op2, final int behavior, final int options, final MetaCharTable metaCharTable) {
this.op = op;
this.op2 = op2;
this.behavior = behavior;
@@ -46,8 +46,8 @@ public final class Syntax implements SyntaxProperties{
public final int oneOrMoreTime;
public final int anyCharAnyTime;
- public MetaCharTable(int esc, int anyChar, int anyTime,
- int zeroOrOneTime, int oneOrMoreTime, int anyCharAnyTime) {
+ public MetaCharTable(final int esc, final int anyChar, final int anyTime,
+ final int zeroOrOneTime, final int oneOrMoreTime, final int anyCharAnyTime) {
this.esc = esc;
this.anyChar = anyChar;
this.anyTime = anyTime;
@@ -61,7 +61,7 @@ public final class Syntax implements SyntaxProperties{
* OP
*
*/
- protected boolean isOp(int opm) {
+ protected boolean isOp(final int opm) {
return (op & opm) != 0;
}
@@ -194,7 +194,7 @@ public final class Syntax implements SyntaxProperties{
* OP
*
*/
- protected boolean isOp2(int opm) {
+ protected boolean isOp2(final int opm) {
return (op2 & opm) != 0;
}
@@ -282,7 +282,7 @@ public final class Syntax implements SyntaxProperties{
* BEHAVIOR
*
*/
- protected boolean isBehavior(int bvm) {
+ protected boolean isBehavior(final int bvm) {
return (behavior & bvm) != 0;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
index 5ac22db6..095bb07e 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
@@ -33,21 +33,21 @@ final class Token {
int getC() {
return INT1;
}
- void setC(int c) {
+ void setC(final int c) {
INT1 = c;
}
int getCode() {
return INT1;
}
- void setCode(int code) {
+ void setCode(final int code) {
INT1 = code;
}
int getAnchor() {
return INT1;
}
- void setAnchor(int anchor) {
+ void setAnchor(final int anchor) {
INT1 = anchor;
}
@@ -55,35 +55,35 @@ final class Token {
int getRepeatLower() {
return INT1;
}
- void setRepeatLower(int lower) {
+ void setRepeatLower(final int lower) {
INT1 = lower;
}
int getRepeatUpper() {
return INT2;
}
- void setRepeatUpper(int upper) {
+ void setRepeatUpper(final int upper) {
INT2 = upper;
}
boolean getRepeatGreedy() {
return INT3 != 0;
}
- void setRepeatGreedy(boolean greedy) {
+ void setRepeatGreedy(final boolean greedy) {
INT3 = greedy ? 1 : 0;
}
boolean getRepeatPossessive() {
return INT4 != 0;
}
- void setRepeatPossessive(boolean possessive) {
+ void setRepeatPossessive(final boolean possessive) {
INT4 = possessive ? 1 : 0;
}
int getBackrefRef() {
return INT2;
}
- void setBackrefRef(int ref1) {
+ void setBackrefRef(final int ref1) {
INT2 = ref1;
}
@@ -91,14 +91,14 @@ final class Token {
int getPropCType() {
return INT1;
}
- void setPropCType(int ctype) {
+ void setPropCType(final int ctype) {
INT1 = ctype;
}
boolean getPropNot() {
return INT2 != 0;
}
- void setPropNot(boolean not) {
+ void setPropNot(final boolean not) {
INT2 = not ? 1 : 0;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java b/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
index 91f7f7ae..2529684d 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
@@ -22,10 +22,11 @@ package jdk.nashorn.internal.runtime.regexp.joni;
/**
* @author <a href="mailto:ola.bini@gmail.com">Ola Bini</a>
*/
+@SuppressWarnings("javadoc")
public interface WarnCallback {
WarnCallback DEFAULT = new WarnCallback() {
@Override
- public void warn(String message) {
+ public void warn(final String message) {
System.err.println(message);
}
};
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java
index 890a0818..09708bcd 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
+@SuppressWarnings("javadoc")
public interface Warnings {
final String INVALID_BACKREFERENCE = "invalid back reference";
final String INVALID_SUBEXP_CALL = "invalid subexp call";
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
index d07a2698..6583da3b 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
@@ -21,12 +21,13 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
+@SuppressWarnings("javadoc")
public final class AnchorNode extends Node implements AnchorType {
public int type;
public Node target;
public int charLength;
- public AnchorNode(int type) {
+ public AnchorNode(final int type) {
this.type = type;
charLength = -1;
}
@@ -37,7 +38,7 @@ public final class AnchorNode extends Node implements AnchorType {
}
@Override
- protected void setChild(Node newChild) {
+ protected void setChild(final Node newChild) {
target = newChild;
}
@@ -46,7 +47,7 @@ public final class AnchorNode extends Node implements AnchorType {
return target;
}
- public void setTarget(Node tgt) {
+ public void setTarget(final Node tgt) {
target = tgt;
tgt.parent = this;
}
@@ -57,36 +58,68 @@ public final class AnchorNode extends Node implements AnchorType {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder();
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder();
value.append("\n type: " + typeToString());
value.append("\n target: " + pad(target, level + 1));
return value.toString();
}
public String typeToString() {
- StringBuilder type = new StringBuilder();
- if (isType(BEGIN_BUF)) type.append("BEGIN_BUF ");
- if (isType(BEGIN_LINE)) type.append("BEGIN_LINE ");
- if (isType(BEGIN_POSITION)) type.append("BEGIN_POSITION ");
- if (isType(END_BUF)) type.append("END_BUF ");
- if (isType(SEMI_END_BUF)) type.append("SEMI_END_BUF ");
- if (isType(END_LINE)) type.append("END_LINE ");
- if (isType(WORD_BOUND)) type.append("WORD_BOUND ");
- if (isType(NOT_WORD_BOUND)) type.append("NOT_WORD_BOUND ");
- if (isType(WORD_BEGIN)) type.append("WORD_BEGIN ");
- if (isType(WORD_END)) type.append("WORD_END ");
- if (isType(PREC_READ)) type.append("PREC_READ ");
- if (isType(PREC_READ_NOT)) type.append("PREC_READ_NOT ");
- if (isType(LOOK_BEHIND)) type.append("LOOK_BEHIND ");
- if (isType(LOOK_BEHIND_NOT)) type.append("LOOK_BEHIND_NOT ");
- if (isType(ANYCHAR_STAR)) type.append("ANYCHAR_STAR ");
- if (isType(ANYCHAR_STAR_ML)) type.append("ANYCHAR_STAR_ML ");
- return type.toString();
+ final StringBuilder sb = new StringBuilder();
+ if (isType(BEGIN_BUF)) {
+ sb.append("BEGIN_BUF ");
+ }
+ if (isType(BEGIN_LINE)) {
+ sb.append("BEGIN_LINE ");
+ }
+ if (isType(BEGIN_POSITION)) {
+ sb.append("BEGIN_POSITION ");
+ }
+ if (isType(END_BUF)) {
+ sb.append("END_BUF ");
+ }
+ if (isType(SEMI_END_BUF)) {
+ sb.append("SEMI_END_BUF ");
+ }
+ if (isType(END_LINE)) {
+ sb.append("END_LINE ");
+ }
+ if (isType(WORD_BOUND)) {
+ sb.append("WORD_BOUND ");
+ }
+ if (isType(NOT_WORD_BOUND)) {
+ sb.append("NOT_WORD_BOUND ");
+ }
+ if (isType(WORD_BEGIN)) {
+ sb.append("WORD_BEGIN ");
+ }
+ if (isType(WORD_END)) {
+ sb.append("WORD_END ");
+ }
+ if (isType(PREC_READ)) {
+ sb.append("PREC_READ ");
+ }
+ if (isType(PREC_READ_NOT)) {
+ sb.append("PREC_READ_NOT ");
+ }
+ if (isType(LOOK_BEHIND)) {
+ sb.append("LOOK_BEHIND ");
+ }
+ if (isType(LOOK_BEHIND_NOT)) {
+ sb.append("LOOK_BEHIND_NOT ");
+ }
+ if (isType(ANYCHAR_STAR)) {
+ sb.append("ANYCHAR_STAR ");
+ }
+ if (isType(ANYCHAR_STAR_ML)) {
+ sb.append("ANYCHAR_STAR_ML ");
+ }
+ return sb.toString();
}
- private boolean isType(int type) {
- return (this.type & type) != 0;
+ private boolean isType(final int t) {
+ return (this.type & t) != 0;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
index 9558ce26..900932e3 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
+@SuppressWarnings("javadoc")
public final class AnyCharNode extends Node {
public AnyCharNode(){}
@@ -33,8 +34,8 @@ public final class AnyCharNode extends Node {
}
@Override
- public String toString(int level) {
- String value = "";
+ public String toString(final int level) {
+ final String value = "";
return value;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
index 478222fd..573c1ec7 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
@@ -21,10 +21,11 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
+@SuppressWarnings("javadoc")
public final class BackRefNode extends StateNode {
public final int backRef;
- public BackRefNode(int backRef, ScanEnvironment env) {
+ public BackRefNode(final int backRef, final ScanEnvironment env) {
this.backRef = backRef;
if (backRef <= env.numMem && env.memNodes[backRef] == null) {
@@ -43,8 +44,8 @@ public final class BackRefNode extends StateNode {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder(super.toString(level));
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder(super.toString(level));
value.append("\n back: ").append(backRef);
return value.toString();
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
index b33eeee0..bcf7aa07 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
@@ -19,7 +19,12 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
-import jdk.nashorn.internal.runtime.regexp.joni.*;
+import jdk.nashorn.internal.runtime.regexp.joni.BitSet;
+import jdk.nashorn.internal.runtime.regexp.joni.CodeRangeBuffer;
+import jdk.nashorn.internal.runtime.regexp.joni.Config;
+import jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper;
+import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
+import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE;
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
@@ -29,6 +34,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException;
+@SuppressWarnings("javadoc")
public final class CClassNode extends Node {
private static final int FLAG_NCCLASS_NOT = 1<<0;
private static final int FLAG_NCCLASS_SHARE = 1<<1;
@@ -94,9 +100,11 @@ public final class CClassNode extends Node {
}
@Override
- public boolean equals(Object other) {
- if (!(other instanceof CClassNode)) return false;
- CClassNode cc = (CClassNode)other;
+ public boolean equals(final Object other) {
+ if (!(other instanceof CClassNode)) {
+ return false;
+ }
+ final CClassNode cc = (CClassNode)other;
return ctype == cc.ctype && isNot() == cc.isNot();
}
@@ -105,16 +113,17 @@ public final class CClassNode extends Node {
if (Config.USE_SHARED_CCLASS_TABLE) {
int hash = 0;
hash += ctype;
- if (isNot()) hash++;
+ if (isNot()) {
+ hash++;
+ }
return hash + (hash >> 5);
- } else {
- return super.hashCode();
}
+ return super.hashCode();
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder();
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder();
value.append("\n flags: " + flagsToString());
value.append("\n bs: " + pad(bs, level + 1));
value.append("\n mbuf: " + pad(mbuf, level + 1));
@@ -123,21 +132,25 @@ public final class CClassNode extends Node {
}
public String flagsToString() {
- StringBuilder flags = new StringBuilder();
- if (isNot()) flags.append("NOT ");
- if (isShare()) flags.append("SHARE ");
- return flags.toString();
+ final StringBuilder f = new StringBuilder();
+ if (isNot()) {
+ f.append("NOT ");
+ }
+ if (isShare()) {
+ f.append("SHARE ");
+ }
+ return f.toString();
}
public boolean isEmpty() {
return mbuf == null && bs.isEmpty();
}
- public void addCodeRangeToBuf(int from, int to) {
+ public void addCodeRangeToBuf(final int from, final int to) {
mbuf = CodeRangeBuffer.addCodeRangeToBuff(mbuf, from, to);
}
- public void addCodeRange(ScanEnvironment env, int from, int to) {
+ public void addCodeRange(final ScanEnvironment env, final int from, final int to) {
mbuf = CodeRangeBuffer.addCodeRange(mbuf, env, from, to);
}
@@ -155,22 +168,22 @@ public final class CClassNode extends Node {
}
// and_cclass
- public void and(CClassNode other) {
- boolean not1 = isNot();
+ public void and(final CClassNode other) {
+ final boolean not1 = isNot();
BitSet bsr1 = bs;
- CodeRangeBuffer buf1 = mbuf;
- boolean not2 = other.isNot();
+ final CodeRangeBuffer buf1 = mbuf;
+ final boolean not2 = other.isNot();
BitSet bsr2 = other.bs;
- CodeRangeBuffer buf2 = other.mbuf;
+ final CodeRangeBuffer buf2 = other.mbuf;
if (not1) {
- BitSet bs1 = new BitSet();
+ final BitSet bs1 = new BitSet();
bsr1.invertTo(bs1);
bsr1 = bs1;
}
if (not2) {
- BitSet bs2 = new BitSet();
+ final BitSet bs2 = new BitSet();
bsr2.invertTo(bs2);
bsr2 = bs2;
}
@@ -202,22 +215,22 @@ public final class CClassNode extends Node {
}
// or_cclass
- public void or(CClassNode other) {
- boolean not1 = isNot();
+ public void or(final CClassNode other) {
+ final boolean not1 = isNot();
BitSet bsr1 = bs;
- CodeRangeBuffer buf1 = mbuf;
- boolean not2 = other.isNot();
+ final CodeRangeBuffer buf1 = mbuf;
+ final boolean not2 = other.isNot();
BitSet bsr2 = other.bs;
- CodeRangeBuffer buf2 = other.mbuf;
+ final CodeRangeBuffer buf2 = other.mbuf;
if (not1) {
- BitSet bs1 = new BitSet();
+ final BitSet bs1 = new BitSet();
bsr1.invertTo(bs1);
bsr1 = bs1;
}
if (not2) {
- BitSet bs2 = new BitSet();
+ final BitSet bs2 = new BitSet();
bsr2.invertTo(bs2);
bsr2 = bs2;
}
@@ -246,8 +259,8 @@ public final class CClassNode extends Node {
}
// add_ctype_to_cc_by_range // Encoding out!
- public void addCTypeByRange(int ctype, boolean not, int sbOut, int mbr[]) {
- int n = mbr[0];
+ public void addCTypeByRange(final int ct, final boolean not, final int sbOut, final int mbr[]) {
+ final int n = mbr[0];
if (!not) {
for (int i=0; i<n; i++) {
@@ -289,10 +302,14 @@ public final class CClassNode extends Node {
// !goto sb_end2!, remove duplication
prev = sbOut;
for (i=0; i<n; i++) {
- if (prev < mbr[2 * i + 1]) addCodeRangeToBuf(prev, mbr[i * 2 + 1] - 1);
+ if (prev < mbr[2 * i + 1]) {
+ addCodeRangeToBuf(prev, mbr[i * 2 + 1] - 1);
+ }
prev = mbr[i * 2 + 2] + 1;
}
- if (prev < 0x7fffffff/*!!!*/) addCodeRangeToBuf(prev, 0x7fffffff);
+ if (prev < 0x7fffffff/*!!!*/) {
+ addCodeRangeToBuf(prev, 0x7fffffff);
+ }
return;
}
bs.set(j);
@@ -307,22 +324,27 @@ public final class CClassNode extends Node {
// !sb_end2:!
prev = sbOut;
for (int i=0; i<n; i++) {
- if (prev < mbr[2 * i + 1]) addCodeRangeToBuf(prev, mbr[i * 2 + 1] - 1);
+ if (prev < mbr[2 * i + 1]) {
+ addCodeRangeToBuf(prev, mbr[i * 2 + 1] - 1);
+ }
prev = mbr[i * 2 + 2] + 1;
}
- if (prev < 0x7fffffff/*!!!*/) addCodeRangeToBuf(prev, 0x7fffffff);
+ if (prev < 0x7fffffff/*!!!*/) {
+ addCodeRangeToBuf(prev, 0x7fffffff);
+ }
}
}
- public void addCType(int ctype, boolean not, ScanEnvironment env, IntHolder sbOut) {
+ public void addCType(final int ctp, final boolean not, final ScanEnvironment env, final IntHolder sbOut) {
+ int ct = ctp;
if (Config.NON_UNICODE_SDW) {
- switch(ctype) {
+ switch (ct) {
case CharacterType.D:
case CharacterType.S:
case CharacterType.W:
- ctype ^= CharacterType.SPECIAL_MASK;
+ ct ^= CharacterType.SPECIAL_MASK;
- if (env.syntax == Syntax.JAVASCRIPT && ctype == CharacterType.SPACE) {
+ if (env.syntax == Syntax.JAVASCRIPT && ct == CharacterType.SPACE) {
// \s in JavaScript includes unicode characters.
break;
}
@@ -330,26 +352,32 @@ public final class CClassNode extends Node {
if (not) {
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
// if (!ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
- if ((AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
+ if ((AsciiCtypeTable[c] & (1 << ct)) == 0) {
+ bs.set(c);
+ }
}
addAllMultiByteRange();
} else {
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
// if (ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
- if ((AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
+ if ((AsciiCtypeTable[c] & (1 << ct)) != 0) {
+ bs.set(c);
+ }
}
}
return;
+ default:
+ break;
}
}
- int[] ranges = EncodingHelper.ctypeCodeRange(ctype, sbOut);
+ final int[] ranges = EncodingHelper.ctypeCodeRange(ct, sbOut);
if (ranges != null) {
- addCTypeByRange(ctype, not, sbOut.value, ranges);
+ addCTypeByRange(ct, not, sbOut.value, ranges);
return;
}
- switch(ctype) {
+ switch(ct) {
case CharacterType.ALPHA:
case CharacterType.BLANK:
case CharacterType.CNTRL:
@@ -363,12 +391,16 @@ public final class CClassNode extends Node {
case CharacterType.ALNUM:
if (not) {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (!EncodingHelper.isCodeCType(c, ctype)) bs.set(c);
+ if (!EncodingHelper.isCodeCType(c, ct)) {
+ bs.set(c);
+ }
}
addAllMultiByteRange();
} else {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (EncodingHelper.isCodeCType(c, ctype)) bs.set(c);
+ if (EncodingHelper.isCodeCType(c, ct)) {
+ bs.set(c);
+ }
}
}
break;
@@ -377,11 +409,15 @@ public final class CClassNode extends Node {
case CharacterType.PRINT:
if (not) {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (!EncodingHelper.isCodeCType(c, ctype)) bs.set(c);
+ if (!EncodingHelper.isCodeCType(c, ct)) {
+ bs.set(c);
+ }
}
} else {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (EncodingHelper.isCodeCType(c, ctype)) bs.set(c);
+ if (EncodingHelper.isCodeCType(c, ct)) {
+ bs.set(c);
+ }
}
addAllMultiByteRange();
}
@@ -390,13 +426,17 @@ public final class CClassNode extends Node {
case CharacterType.WORD:
if (!not) {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (EncodingHelper.isWord(c)) bs.set(c);
+ if (EncodingHelper.isWord(c)) {
+ bs.set(c);
+ }
}
addAllMultiByteRange();
} else {
for (int c=0; c<BitSet.SINGLE_BYTE_SIZE; c++) {
- if (!EncodingHelper.isWord(c)) bs.set(c);
+ if (!EncodingHelper.isWord(c)) {
+ bs.set(c);
+ }
}
}
break;
@@ -416,8 +456,10 @@ public final class CClassNode extends Node {
public CCSTATE state;
}
- public void nextStateClass(CCStateArg arg, ScanEnvironment env) {
- if (arg.state == CCSTATE.RANGE) throw new SyntaxException(ErrorMessages.ERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE);
+ public void nextStateClass(final CCStateArg arg, final ScanEnvironment env) {
+ if (arg.state == CCSTATE.RANGE) {
+ throw new SyntaxException(ErrorMessages.ERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE);
+ }
if (arg.state == CCSTATE.VALUE && arg.type != CCVALTYPE.CLASS) {
if (arg.type == CCVALTYPE.SB) {
@@ -430,12 +472,14 @@ public final class CClassNode extends Node {
arg.type = CCVALTYPE.CLASS;
}
- public void nextStateValue(CCStateArg arg, ScanEnvironment env) {
+ public void nextStateValue(final CCStateArg arg, final ScanEnvironment env) {
switch(arg.state) {
case VALUE:
if (arg.type == CCVALTYPE.SB) {
- if (arg.vs > 0xff) throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE);
+ if (arg.vs > 0xff) {
+ throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE);
+ }
bs.set(arg.vs);
} else if (arg.type == CCVALTYPE.CODE_POINT) {
addCodeRange(env, arg.vs, arg.vs);
@@ -445,16 +489,17 @@ public final class CClassNode extends Node {
case RANGE:
if (arg.inType == arg.type) {
if (arg.inType == CCVALTYPE.SB) {
- if (arg.vs > 0xff || arg.v > 0xff) throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE);
+ if (arg.vs > 0xff || arg.v > 0xff) {
+ throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE);
+ }
if (arg.vs > arg.v) {
if (env.syntax.allowEmptyRangeInCC()) {
// goto ccs_range_end
arg.state = CCSTATE.COMPLETE;
break;
- } else {
- throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
+ throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
bs.setRange(arg.vs, arg.v);
} else {
@@ -466,9 +511,8 @@ public final class CClassNode extends Node {
// goto ccs_range_end
arg.state = CCSTATE.COMPLETE;
break;
- } else {
- throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
+ throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
bs.setRange(arg.vs, arg.v < 0xff ? arg.v : 0xff);
addCodeRange(env, arg.vs, arg.v);
@@ -493,7 +537,7 @@ public final class CClassNode extends Node {
}
// onig_is_code_in_cc_len
- public boolean isCodeInCCLength(int code) {
+ public boolean isCodeInCCLength(final int code) {
boolean found;
if (code > 0xff) {
@@ -504,13 +548,12 @@ public final class CClassNode extends Node {
if (isNot()) {
return !found;
- } else {
- return found;
}
+ return found;
}
// onig_is_code_in_cc
- public boolean isCodeInCC(int code) {
+ public boolean isCodeInCC(final int code) {
return isCodeInCCLength(code);
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
index e8bcb303..c07bb369 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
@@ -20,35 +20,40 @@
package jdk.nashorn.internal.runtime.regexp.joni.ast;
import java.util.Set;
-
import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
+@SuppressWarnings("javadoc")
public final class ConsAltNode extends Node {
public Node car;
public ConsAltNode cdr;
private int type; // List or Alt
- private ConsAltNode(Node car, ConsAltNode cdr, int type) {
+ private ConsAltNode(final Node car, final ConsAltNode cdr, final int type) {
this.car = car;
- if (car != null) car.parent = this;
+ if (car != null) {
+ car.parent = this;
+ }
this.cdr = cdr;
- if (cdr != null) cdr.parent = this;
+ if (cdr != null) {
+ cdr.parent = this;
+ }
this.type = type;
}
- public static ConsAltNode newAltNode(Node left, ConsAltNode right) {
+ public static ConsAltNode newAltNode(final Node left, final ConsAltNode right) {
return new ConsAltNode(left, right, ALT);
}
- public static ConsAltNode newListNode(Node left, ConsAltNode right) {
+ public static ConsAltNode newListNode(final Node left, final ConsAltNode right) {
return new ConsAltNode(left, right, LIST);
}
- public static ConsAltNode listAdd(ConsAltNode list, Node x) {
- ConsAltNode n = newListNode(x, null);
+ public static ConsAltNode listAdd(final ConsAltNode listp, final Node x) {
+ final ConsAltNode n = newListNode(x, null);
+ ConsAltNode list = listp;
if (list != null) {
while (list.cdr != null) {
@@ -73,7 +78,7 @@ public final class ConsAltNode extends Node {
}
@Override
- protected void setChild(Node newChild) {
+ protected void setChild(final Node newChild) {
car = newChild;
}
@@ -83,13 +88,13 @@ public final class ConsAltNode extends Node {
}
@Override
- public void swap(Node with) {
+ public void swap(final Node with) {
if (cdr != null) {
cdr.parent = with;
if (with instanceof ConsAltNode) {
- ConsAltNode withCan = (ConsAltNode)with;
+ final ConsAltNode withCan = (ConsAltNode)with;
withCan.cdr.parent = this;
- ConsAltNode tmp = cdr;
+ final ConsAltNode tmp = cdr;
cdr = withCan.cdr;
withCan.cdr = tmp;
}
@@ -98,7 +103,7 @@ public final class ConsAltNode extends Node {
}
@Override
- public void verifyTree(Set<Node> set, WarnCallback warnings) {
+ public void verifyTree(final Set<Node> set, final WarnCallback warnings) {
if (!set.contains(this)) {
set.add(this);
if (car != null) {
@@ -116,13 +121,13 @@ public final class ConsAltNode extends Node {
}
}
- public Node setCar(Node ca) {
+ public Node setCar(final Node ca) {
car = ca;
ca.parent = this;
return car;
}
- public ConsAltNode setCdr(ConsAltNode cd) {
+ public ConsAltNode setCdr(final ConsAltNode cd) {
cdr = cd;
cd.parent = this;
return cdr;
@@ -141,8 +146,8 @@ public final class ConsAltNode extends Node {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder();
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder();
value.append("\n car: " + pad(car, level + 1));
value.append("\n cdr: " + (cdr == null ? "NULL" : cdr.toString()));
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
index e494c1cc..95110115 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
@@ -22,6 +22,7 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.Option;
import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
+@SuppressWarnings("javadoc")
public final class EncloseNode extends StateNode implements EncloseType {
public final int type; // enclose type
@@ -35,7 +36,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
public int optCount; // referenced count in optimize_node_left()
// node_new_enclose / onig_node_new_enclose
- public EncloseNode(int type) {
+ public EncloseNode(final int type) {
this.type = type;
callAddr = -1;
}
@@ -46,7 +47,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
}
// node_new_option
- public EncloseNode(int option, int i) {
+ public EncloseNode(final int option, final int i) {
this(OPTION);
this.option = option;
}
@@ -57,7 +58,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
}
@Override
- protected void setChild(Node newChild) {
+ protected void setChild(final Node newChild) {
target = newChild;
}
@@ -66,7 +67,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
return target;
}
- public void setTarget(Node tgt) {
+ public void setTarget(final Node tgt) {
target = tgt;
tgt.parent = this;
}
@@ -77,8 +78,8 @@ public final class EncloseNode extends StateNode implements EncloseType {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder(super.toString(level));
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder(super.toString(level));
value.append("\n type: " + typeToString());
value.append("\n regNum: " + regNum);
value.append("\n option: " + Option.toString(option));
@@ -93,7 +94,7 @@ public final class EncloseNode extends StateNode implements EncloseType {
}
public String typeToString() {
- StringBuilder types = new StringBuilder();
+ final StringBuilder types = new StringBuilder();
if (isStopBacktrack()) types.append("STOP_BACKTRACK ");
if (isMemory()) types.append("MEMORY ");
if (isOption()) types.append("OPTION ");
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
index fdf9687d..9961432e 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
@@ -20,11 +20,11 @@
package jdk.nashorn.internal.runtime.regexp.joni.ast;
import java.util.Set;
-
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
+@SuppressWarnings("javadoc")
public abstract class Node implements NodeType {
public Node parent;
@@ -34,10 +34,14 @@ public abstract class Node implements NodeType {
return 1 << getType();
}
- protected void setChild(Node tgt){} // default definition
- protected Node getChild(){return null;} // default definition
+ protected void setChild(final Node tgt) {
+ //empty, default definition
+ }
+ protected Node getChild() {
+ return null; // default definition
+ }
- public void swap(Node with) {
+ public void swap(final Node with) {
Node tmp;
//if (getChild() != null) getChild().parent = with;
@@ -47,9 +51,13 @@ public abstract class Node implements NodeType {
//setChild(with.getChild());
//with.setChild(tmp);
- if (parent != null) parent.setChild(with);
+ if (parent != null) {
+ parent.setChild(with);
+ }
- if (with.parent != null) with.parent.setChild(this);
+ if (with.parent != null) {
+ with.parent.setChild(this);
+ }
tmp = parent;
parent = with.parent;
@@ -57,7 +65,7 @@ public abstract class Node implements NodeType {
}
// overridden by ConsAltNode and CallNode
- public void verifyTree(Set<Node> set, WarnCallback warnings) {
+ public void verifyTree(final Set<Node> set, final WarnCallback warnings) {
if (!set.contains(this) && getChild() != null) {
set.add(this);
if (getChild().parent != this) {
@@ -76,22 +84,28 @@ public abstract class Node implements NodeType {
@Override
public final String toString() {
- StringBuilder s = new StringBuilder();
+ final StringBuilder s = new StringBuilder();
s.append("<" + getAddressName() + " (" + (parent == null ? "NULL" : parent.getAddressName()) + ")>");
return s + toString(0);
}
- protected static String pad(Object value, int level) {
- if (value == null) return "NULL";
+ protected static String pad(final Object value, final int level) {
+ if (value == null) {
+ return "NULL";
+ }
- StringBuilder pad = new StringBuilder(" ");
- for (int i=0; i<level; i++) pad.append(pad);
+ final StringBuilder pad = new StringBuilder(" ");
+ for (int i=0; i<level; i++) {
+ pad.append(pad);
+ }
return value.toString().replace("\n", "\n" + pad);
}
public final boolean isInvalidQuantifier() {
- if (!Config.VANILLA) return false;
+ if (!Config.VANILLA) {
+ return false;
+ }
ConsAltNode node;
@@ -108,14 +122,18 @@ public abstract class Node implements NodeType {
case LIST:
node = (ConsAltNode)this;
do {
- if (!node.car.isInvalidQuantifier()) return false;
+ if (!node.car.isInvalidQuantifier()) {
+ return false;
+ }
} while ((node = node.cdr) != null);
return false;
case ALT:
node = (ConsAltNode)this;
do {
- if (node.car.isInvalidQuantifier()) return true;
+ if (node.car.isInvalidQuantifier()) {
+ return true;
+ }
} while ((node = node.cdr) != null);
break;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
index 7d84accc..d4be3780 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
@@ -19,12 +19,18 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.A;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.AQ;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.ASIS;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.DEL;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.PQ_Q;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.P_QQ;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.QQ;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
-import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
-
+@SuppressWarnings("javadoc")
public final class QuantifierNode extends StateNode {
public Node target;
@@ -66,13 +72,15 @@ public final class QuantifierNode extends StateNode {
};
- public QuantifierNode(int lower, int upper, boolean byNumber) {
+ public QuantifierNode(final int lower, final int upper, final boolean byNumber) {
this.lower = lower;
this.upper = upper;
greedy = true;
targetEmptyInfo = TargetInfo.ISNOT_EMPTY;
- if (byNumber) setByNumber();
+ if (byNumber) {
+ setByNumber();
+ }
}
@Override
@@ -81,7 +89,7 @@ public final class QuantifierNode extends StateNode {
}
@Override
- protected void setChild(Node newChild) {
+ protected void setChild(final Node newChild) {
target = newChild;
}
@@ -90,13 +98,13 @@ public final class QuantifierNode extends StateNode {
return target;
}
- public void setTarget(Node tgt) {
+ public void setTarget(final Node tgt) {
target = tgt;
tgt.parent = this;
}
- public StringNode convertToString(int flag) {
- StringNode sn = new StringNode();
+ public StringNode convertToString(final int flag) {
+ final StringNode sn = new StringNode();
sn.flag = flag;
sn.swap(this);
return sn;
@@ -108,8 +116,8 @@ public final class QuantifierNode extends StateNode {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder(super.toString(level));
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder(super.toString(level));
value.append("\n target: " + pad(target, level + 1));
value.append("\n lower: " + lower);
value.append("\n upper: " + upper);
@@ -130,23 +138,33 @@ public final class QuantifierNode extends StateNode {
protected int popularNum() {
if (greedy) {
if (lower == 0) {
- if (upper == 1) return 0;
- else if (isRepeatInfinite(upper)) return 1;
+ if (upper == 1) {
+ return 0;
+ } else if (isRepeatInfinite(upper)) {
+ return 1;
+ }
} else if (lower == 1) {
- if (isRepeatInfinite(upper)) return 2;
+ if (isRepeatInfinite(upper)) {
+ return 2;
+ }
}
} else {
if (lower == 0) {
- if (upper == 1) return 3;
- else if (isRepeatInfinite(upper)) return 4;
+ if (upper == 1) {
+ return 3;
+ } else if (isRepeatInfinite(upper)) {
+ return 4;
+ }
} else if (lower == 1) {
- if (isRepeatInfinite(upper)) return 5;
+ if (isRepeatInfinite(upper)) {
+ return 5;
+ }
}
}
return -1;
}
- protected void set(QuantifierNode other) {
+ protected void set(final QuantifierNode other) {
setTarget(other.target);
other.target = null;
lower = other.lower;
@@ -161,11 +179,13 @@ public final class QuantifierNode extends StateNode {
isRefered = other.isRefered;
}
- public void reduceNestedQuantifier(QuantifierNode other) {
- int pnum = popularNum();
- int cnum = other.popularNum();
+ public void reduceNestedQuantifier(final QuantifierNode other) {
+ final int pnum = popularNum();
+ final int cnum = other.popularNum();
- if (pnum < 0 || cnum < 0) return;
+ if (pnum < 0 || cnum < 0) {
+ return;
+ }
switch(REDUCE_TABLE[cnum][pnum]) {
case DEL:
@@ -218,22 +238,27 @@ public final class QuantifierNode extends StateNode {
case ASIS:
setTarget(other);
return;
+
+ default:
+ break;
}
// ??? remove the parent from target ???
other.target = null; // remove target from reduced quantifier
}
@SuppressWarnings("fallthrough")
- public int setQuantifier(Node tgt, boolean group, ScanEnvironment env, char[] chars, int p, int end) {
- if (lower == 1 && upper == 1) return 1;
+ public int setQuantifier(final Node tgt, final boolean group, final ScanEnvironment env, final char[] chars, final int p, final int end) {
+ if (lower == 1 && upper == 1) {
+ return 1;
+ }
switch(tgt.getType()) {
case STR:
if (!group) {
- StringNode sn = (StringNode)tgt;
+ final StringNode sn = (StringNode)tgt;
if (sn.canBeSplit()) {
- StringNode n = sn.splitLastChar();
+ final StringNode n = sn.splitLastChar();
if (n != null) {
setTarget(n);
return 2;
@@ -245,9 +270,9 @@ public final class QuantifierNode extends StateNode {
case QTFR:
/* check redundant double repeat. */
/* verbose warn (?:.?)? etc... but not warn (.?)? etc... */
- QuantifierNode qnt = (QuantifierNode)tgt;
- int nestQNum = popularNum();
- int targetQNum = qnt.popularNum();
+ final QuantifierNode qnt = (QuantifierNode)tgt;
+ final int nestQNum = popularNum();
+ final int targetQNum = qnt.popularNum();
if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
@@ -290,7 +315,7 @@ public final class QuantifierNode extends StateNode {
}
public static final int REPEAT_INFINITE = -1;
- public static boolean isRepeatInfinite(int n) {
+ public static boolean isRepeatInfinite(final int n) {
return n == REPEAT_INFINITE;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
index d2b3c954..2d75ebc8 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
@@ -21,16 +21,17 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeStatus;
+@SuppressWarnings("javadoc")
public abstract class StateNode extends Node implements NodeStatus {
protected int state;
@Override
- public String toString(int level) {
+ public String toString(final int level) {
return "\n state: " + stateToString();
}
public String stateToString() {
- StringBuilder states = new StringBuilder();
+ final StringBuilder states = new StringBuilder();
if (isMinFixed()) states.append("MIN_FIXED ");
if (isMaxFixed()) states.append("MAX_FIXED ");
if (isMark1()) states.append("MARK1 ");
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
index 0618ddf3..985c95e6 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
@@ -22,6 +22,7 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType;
+@SuppressWarnings("javadoc")
public final class StringNode extends Node implements StringType {
private static final int NODE_STR_MARGIN = 16;
@@ -38,14 +39,14 @@ public final class StringNode extends Node implements StringType {
this.chars = new char[NODE_STR_BUF_SIZE];
}
- public StringNode(char[] chars, int p, int end) {
+ public StringNode(final char[] chars, final int p, final int end) {
this.chars = chars;
this.p = p;
this.end = end;
setShared();
}
- public StringNode(char c) {
+ public StringNode(final char c) {
this();
chars[end++] = c;
}
@@ -53,10 +54,10 @@ public final class StringNode extends Node implements StringType {
/* Ensure there is ahead bytes available in node's buffer
* (assumes that the node is not shared)
*/
- public void ensure(int ahead) {
- int len = (end - p) + ahead;
+ public void ensure(final int ahead) {
+ final int len = (end - p) + ahead;
if (len >= chars.length) {
- char[] tmp = new char[len + NODE_STR_MARGIN];
+ final char[] tmp = new char[len + NODE_STR_MARGIN];
System.arraycopy(chars, p, tmp, 0, end - p);
chars = tmp;
}
@@ -64,10 +65,10 @@ public final class StringNode extends Node implements StringType {
/* COW and/or ensure there is ahead bytes available in node's buffer
*/
- private void modifyEnsure(int ahead) {
+ private void modifyEnsure(final int ahead) {
if (isShared()) {
- int len = (end - p) + ahead;
- char[] tmp = new char[len + NODE_STR_MARGIN];
+ final int len = (end - p) + ahead;
+ final char[] tmp = new char[len + NODE_STR_MARGIN];
System.arraycopy(chars, p, tmp, 0, end - p);
chars = tmp;
end = end - p;
@@ -89,8 +90,8 @@ public final class StringNode extends Node implements StringType {
}
@Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder();
+ public String toString(final int level) {
+ final StringBuilder value = new StringBuilder();
value.append("\n bytes: '");
for (int i=p; i<end; i++) {
if (chars[i] >= 0x20 && chars[i] < 0x7f) {
@@ -111,7 +112,7 @@ public final class StringNode extends Node implements StringType {
StringNode n = null;
if (end > p) {
- int prev = EncodingHelper.prevCharHead(p, end);
+ final int prev = EncodingHelper.prevCharHead(p, end);
if (prev != -1 && prev > p) { /* can be splitted. */
n = new StringNode(chars, prev, end);
if (isRaw()) n.setRaw();
@@ -125,26 +126,26 @@ public final class StringNode extends Node implements StringType {
return end > p && 1 < (end - p);
}
- public void set(char[] chars, int p, int end) {
+ public void set(final char[] chars, final int p, final int end) {
this.chars = chars;
this.p = p;
this.end = end;
setShared();
}
- public void cat(char[] cat, int catP, int catEnd) {
- int len = catEnd - catP;
+ public void cat(final char[] cat, final int catP, final int catEnd) {
+ final int len = catEnd - catP;
modifyEnsure(len);
System.arraycopy(cat, catP, chars, end, len);
end += len;
}
- public void cat(char c) {
+ public void cat(final char c) {
modifyEnsure(1);
chars[end++] = c;
}
- public void catCode(int code) {
+ public void catCode(final int code) {
cat((char)code);
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java
index d3e8ccb6..38da6ae6 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AnchorType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface AnchorType {
final int BEGIN_BUF = (1<<0);
final int BEGIN_LINE = (1<<1);
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java
index 543b170f..ba96564d 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Arguments.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface Arguments {
final int SPECIAL = -1;
final int NON = 0;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java
index afde7610..ba4bf756 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/AsmConstants.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface AsmConstants {
final int THIS = 0;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java
index 6760b6a9..bd98a6b1 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCSTATE.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public enum CCSTATE {
VALUE,
RANGE,
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java
index fa20a4c6..f45f94a5 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/CCVALTYPE.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public enum CCVALTYPE {
SB,
CODE_POINT,
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java
index 88aba987..f82e8af9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/EncloseType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface EncloseType {
final int MEMORY = 1<<0;
final int OPTION = 1<<1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java
index 2c9d338e..82c7682c 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/MetaChar.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface MetaChar {
final int ESCAPE = 0;
final int ANYCHAR = 1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java
index ef983d79..b5e0ea4c 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeStatus.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface NodeStatus {
/* status bits */
final int NST_MIN_FIXED = (1<<0);
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java
index c3061ffd..fc3670b9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/NodeType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface NodeType {
/* node type */
final int STR = 0;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java
index cb5f3d10..bb31740d 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPCode.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface OPCode {
final int FINISH = 0; /* matching process terminator (no more alternative) */
final int END = 1; /* pattern code terminator (success end) */
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java
index c0a8b148..870a5ebc 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/OPSize.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface OPSize {
// this might be helpful for potential byte[] migration
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java
index dd3bd6d7..5f1a3cd4 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/RegexState.java
@@ -20,6 +20,7 @@
package jdk.nashorn.internal.runtime.regexp.joni.constants;
// we dont need this ATM
+@SuppressWarnings("javadoc")
public interface RegexState {
final int NORMAL = 0;
final int SEARCHING = 1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java
index efe7e4f5..67bd0e1a 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackPopLevel.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface StackPopLevel {
final int FREE = 0;
final int MEM_START = 1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java
index 0e0ebc6a..539804f9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StackType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface StackType {
/** stack **/
final int INVALID_STACK_INDEX = -1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java
index d16c93ea..33347a16 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/StringType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface StringType {
final int NSTR_RAW = 1<<0;
final int NSTR_AMBIG = 1<<1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java
index 3da439a6..8f8b0647 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/SyntaxProperties.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface SyntaxProperties {
/* syntax (operators); */
final int OP_VARIABLE_META_CHARACTERS = (1<<0);
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
index 0c965596..8dfb92bd 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface TargetInfo {
final int ISNOT_EMPTY = 0;
final int IS_EMPTY = 1;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java
index 342455f2..72b94f69 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TokenType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public enum TokenType {
EOT, /* end of token */
RAW_BYTE,
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java
index 8cc36672..9b6650de 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Traverse.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
+@SuppressWarnings("javadoc")
public interface Traverse {
final int TRAVERSE_CALLBACK_AT_FIRST = 1;
final int TRAVERSE_CALLBACK_AT_LAST = 2;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java
index 79e1c01a..d248efe1 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/CharacterType.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
+@SuppressWarnings("javadoc")
public interface CharacterType {
final int NEWLINE = 0;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java
index 248538b8..06fc7fb0 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/IntHolder.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
+@SuppressWarnings("javadoc")
public class IntHolder {
public int value;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
index 5c024577..18bfa0d9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
@@ -19,12 +19,13 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
+@SuppressWarnings("javadoc")
public final class ObjPtr<T> {
public ObjPtr() {
this(null);
}
- public ObjPtr(T p) {
+ public ObjPtr(final T p) {
this.p = p;
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java
index 66ec0cfe..3c835d7b 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java
@@ -19,6 +19,7 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.exception;
+@SuppressWarnings("javadoc")
public interface ErrorMessages {
/* from jcodings */
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
index 47028aea..22642dd0 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
@@ -19,10 +19,11 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.exception;
+@SuppressWarnings("javadoc")
public class InternalException extends JOniException{
private static final long serialVersionUID = -3871816465397927992L;
- public InternalException(String message) {
+ public InternalException(final String message) {
super(message);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
index a5f237f5..537bf0f3 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
@@ -19,10 +19,11 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.exception;
+@SuppressWarnings("javadoc")
public class JOniException extends RuntimeException{
private static final long serialVersionUID = -6027192180014164667L;
- public JOniException(String message) {
+ public JOniException(final String message) {
super(message);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
index e53fe36c..4698ab76 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
@@ -19,10 +19,11 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.exception;
+@SuppressWarnings("javadoc")
public class SyntaxException extends JOniException{
private static final long serialVersionUID = 7862720128961874288L;
- public SyntaxException(String message) {
+ public SyntaxException(final String message) {
super(message);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
index 597fe221..75b590ec 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
@@ -19,14 +19,15 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni.exception;
-public class ValueException extends SyntaxException{
+@SuppressWarnings("javadoc")
+public class ValueException extends SyntaxException {
private static final long serialVersionUID = -196013852479929134L;
- public ValueException(String message) {
+ public ValueException(final String message) {
super(message);
}
- public ValueException(String message, String str) {
+ public ValueException(final String message, final String str) {
super(message.replaceAll("%n", str));
}
diff --git a/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index c98c1c7c..119277df 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -58,6 +58,7 @@ parser.error.regex.unsupported.flag=Unsupported RegExp flag: {0}
parser.error.regex.repeated.flag=Repeated RegExp flag: {0}
parser.error.regex.syntax={0}
parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON
+parser.error.missing.const.assignment=Missing assignment to constant "{0}"
# strict mode error messages
parser.error.strict.no.with="with" statement cannot be used in strict mode
@@ -72,14 +73,17 @@ type.error.strict.getter.setter.poison=In strict mode, "caller", "callee", and "
type.error.not.an.object={0} is not an Object
type.error.not.a.boolean={0} is not a Boolean
type.error.not.a.date={0} is not a Date
+type.error.not.a.java.importer={0} is not a JavaImporter object
type.error.not.a.number={0} is not a Number
type.error.not.a.regexp={0} is not a RegExp
type.error.not.a.string={0} is not a String
type.error.not.a.function={0} is not a function
type.error.not.a.constructor={0} is not a constructor function
type.error.not.a.file={0} is not a File
+type.error.not.a.numeric.array={0} is not a numeric array
type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
-type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
+type.error.not.an.arraybuffer.in.dataview=First argument to DataView constructor must be an ArrayBuffer
+type.error.no.reflection.with.classfilter=Java reflection not supported when class filter is present
# operations not permitted on undefined
type.error.cant.call.undefined=Cannot call undefined
@@ -89,8 +93,11 @@ type.error.cant.delete.property.of.undefined=Cannot delete property "{0}" of und
# other wrong usages of property
type.error.property.has.no.setter=Cannot set property "{0}" of {1} that has only a getter
-type.error.cant.set.proto.to.non.object=Cannot set Object {0}'s __proto__ to be a non-object like {1}
+type.error.cant.set.proto.to.non.object=Cannot set Object {0}''s __proto__ to be a non-object like {1}
type.error.no.such.function={1} has no such function "{0}"
+type.error.no.such.java.class=No such Java class: {0}
+type.error.no.such.java.constructor=No such Java constructor: {0}
+type.error.improper.constructor.signature=Java constructor signature invalid: {0}
type.error.cant.get.property=Cannot get property "{0}" of {1}
type.error.cant.set.property=Cannot set property "{0}" of {1}
type.error.cant.delete.property=Cannot delete property "{0}" of {1}
@@ -109,6 +116,7 @@ type.error.instanceof.on.non.object=instanceof must be called with a javascript
type.error.cannot.convert.to.interface=object {0} cannot be converted to {1} due to "{2}"
type.error.array.reduce.invalid.init=invalid initialValue for Array.prototype.reduce
type.error.array.reduceright.invalid.init=invalid initialValue for Array.prototype.reduceRight
+type.error.assign.constant=Assignment to constant "{0}"
type.error.cannot.get.default.string=Cannot get default string value
type.error.cannot.get.default.number=Cannot get default number value
type.error.cant.apply.with.to.null=Cannot apply "with" to null
@@ -119,10 +127,10 @@ type.error.prototype.not.an.object="prototype" of {0} is not an Object, it is {1
type.error.cant.load.script=Cannot load script from {0}
type.error.JSON.stringify.cyclic=JSON.stringify got a cyclic data structure
type.error.cant.convert.string.to.char=Cannot convert string to character; its length must be exactly 1
-type.error.cant.convert.number.to.char=Cannot convert number to character; it's out of 0-65535 range
+type.error.cant.convert.number.to.char=Cannot convert number to character; it is out of 0-65535 range
type.error.cant.convert.to.java.string=Cannot convert object of type {0} to a Java argument of string type
type.error.cant.convert.to.java.number=Cannot convert object of type {0} to a Java argument of number type
-type.error.cant.convert.to.javascript.array=Can only convert Java arrays and lists to JavaScript arrays. Can't convert object of type {0}.
+type.error.cant.convert.to.javascript.array=Can only convert Java arrays and lists to JavaScript arrays. Cannot convert object of type {0}.
type.error.extend.expects.at.least.one.argument=Java.extend needs at least one argument.
type.error.extend.expects.at.least.one.type.argument=Java.extend needs at least one type argument.
type.error.extend.expects.java.types=Java.extend needs Java types as its arguments.
@@ -135,9 +143,10 @@ type.error.extend.ERROR_NO_COMMON_LOADER=Can not find a common class loader for
type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method.
type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures.
type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
-type.error.method.not.constructor=Java method {0} can't be used as a constructor.
+type.error.method.not.constructor=Java method {0} cannot be used as a constructor.
type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
+type.error.constructor.requires.new=Constructor {0} requires "new".
type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}.
range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor
@@ -149,12 +158,16 @@ range.error.invalid.precision=precision argument toPrecision() must be in [1, 21
range.error.invalid.radix=radix argument must be in [2, 36]
range.error.invalid.date=Invalid Date
range.error.too.many.errors=Script contains too many errors: {0} errors
+range.error.concat.string.too.big=Concatenated String is too big
reference.error.not.defined="{0}" is not defined
reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment
syntax.error.invalid.json=Invalid JSON: {0}
syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
+syntax.error.redeclare.variable=Variable "{0}" has already been declared
+syntax.error.assign.constant=Assignment to constant "{0}"
+syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
io.error.cant.write=cannot write "{0}"
config.error.no.dest=no destination directory supplied
diff --git a/src/jdk/nashorn/internal/runtime/resources/Options.properties b/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 9262a401..57943e01 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -177,7 +177,7 @@ nashorn.option.log = { \
is_undocumented=true, \
params="<module:level>,*", \
desc="Enable logging of a given level for a given number of sub systems. \
- [for example: --log=fields:finest,codegen:info]", \
+ [for example: --log=fields:finest,codegen:info].", \
type=Log \
}
@@ -197,7 +197,15 @@ nashorn.option.debug.locals = { \
nashorn.option.lazy.compilation = { \
name="--lazy-compilation", \
is_undocumented=true, \
- desc="EXPERIMENTAL: Use lazy code generation strategies - do not compile the entire script at once." \
+ desc="Use lazy code generation strategies - do not compile the entire script at once.", \
+ default=true \
+}
+
+nashorn.option.optimistic.types = { \
+ name="--optimistic-types", \
+ short_name="-ot", \
+ desc="Use optimistic type assumptions with deoptimizing recompilation. This makes the compiler try, for any program symbol whose type cannot be proven at compile time, to type it as narrow and primitive as possible. If the runtime encounters an error because symbol type is too narrow, a wider method will be generated until steady stage is reached. While this produces as optimal Java Bytecode as possible, erroneous type guesses will lead to longer warmup. Optimistic typing is currently disabled by default, but can be enabled for significantly better peak performance.", \
+ default=false \
}
nashorn.option.loader.per.compile = { \
@@ -211,23 +219,23 @@ nashorn.option.no.java = { \
name="--no-java", \
short_name="-nj", \
is_undocumented=true, \
- desc="No Java support", \
+ desc="Disable Java support.", \
default=false \
}
-nashorn.option.no.syntax.extensions = { \
- name="--no-syntax-extensions", \
- short_name="-nse", \
- is_undocumented=true, \
- desc="No non-standard syntax extensions", \
- default=false \
+nashorn.option.no.syntax.extensions = { \
+ name="--no-syntax-extensions", \
+ short_name="-nse", \
+ is_undocumented=true, \
+ desc="Disallow non-standard syntax extensions.", \
+ default=false \
}
nashorn.option.no.typed.arrays = { \
name="--no-typed-arrays", \
short_name="-nta", \
is_undocumented=true, \
- desc="No Typed arrays support", \
+ desc="Disable typed arrays support.", \
default=false \
}
@@ -266,8 +274,11 @@ nashorn.option.print.lower.ast = { \
nashorn.option.print.code = { \
name="--print-code", \
+ short_name="-pc", \
is_undocumented=true, \
- desc="Print bytecode." \
+ params="[dir:<output-dir>,function:<name>]", \
+ type=keyvalues, \
+ desc="Print generated bytecode. If a directory is specified, nothing will be dumped to stderr. Also, in that case, .dot files will be generated for all functions or for the function with the specified name only." \
}
nashorn.option.print.mem.usage = { \
@@ -284,12 +295,14 @@ nashorn.option.print.no.newline = { \
nashorn.option.print.parse = { \
name="--print-parse", \
+ short_name="-pp", \
is_undocumented=true, \
desc="Print the parse tree." \
}
nashorn.option.print.lower.parse = { \
name="--print-lower-parse", \
+ short_name="-plp", \
is_undocumented=true, \
desc="Print the parse tree after lowering." \
}
@@ -300,12 +313,6 @@ nashorn.option.print.symbols = { \
desc="Print the symbol table." \
}
-nashorn.option.range.analysis = { \
- name="--range-analysis", \
- is_undocumented=true, \
- desc="EXPERIMENTAL: Do range analysis using known compile time types, and try to narrow number types" \
-}
-
nashorn.option.D = { \
name="-D", \
desc="-Dname=value. Set a system property. This option can be repeated.", \
@@ -322,28 +329,28 @@ nashorn.option.scripting = { \
desc="Enable scripting features." \
}
-nashorn.option.specialize.calls = { \
- name="--specialize-calls", \
- is_undocumented=true, \
- type=String, \
- params="[=function_1,...,function_n]", \
- desc="EXPERIMENTAL: Specialize all or a set of method according to callsite parameter types" \
+nashorn.option.language = { \
+ name="--language", \
+ type=String, \
+ params=[es5|es6], \
+ default=es5, \
+ desc="Specify ECMAScript language version." \
}
-nashorn.option.stdout = { \
- name="--stdout", \
- is_undocumented=true, \
- type=String, \
- params="<output console>", \
- desc="Redirect stdout to a filename or to another tty, e.g. stderr" \
+nashorn.option.stdout = { \
+ name="--stdout", \
+ is_undocumented=true, \
+ type=String, \
+ params="<output console>", \
+ desc="Redirect stdout to a filename or to another tty, e.g. stderr." \
}
-nashorn.option.stderr = { \
- name="--stderr", \
- is_undocumented=true, \
- type=String, \
- params="<output console>", \
- desc="Redirect stderr to a filename or to another tty, e.g. stdout" \
+nashorn.option.stderr = { \
+ name="--stderr", \
+ is_undocumented=true, \
+ type=String, \
+ params="<output console>", \
+ desc="Redirect stderr to a filename or to another tty, e.g. stdout." \
}
nashorn.option.timezone = { \
@@ -363,14 +370,14 @@ nashorn.option.locale = { \
type=Locale \
}
-nashorn.option.trace.callsites = { \
- name="--trace-callsites", \
- short_name="-tcs", \
- is_undocumented=true, \
- type=keyvalues, \
- params="[=[option,]*]", \
- desc="Enable callsite trace mode. Options are: miss [trace callsite misses] \
- enterexit [trace callsite enter/exit], objects [print object properties]" \
+nashorn.option.trace.callsites = { \
+ name="--trace-callsites", \
+ short_name="-tcs", \
+ is_undocumented=true, \
+ type=keyvalues, \
+ params="[=[option,]*]", \
+ desc="Enable callsite trace mode. Options are: miss [trace callsite misses] \
+ enterexit [trace callsite enter/exit], objects [print object properties]." \
}
nashorn.option.verify.code = { \
diff --git a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js
index 85e2161c..6c27e2a6 100644
--- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js
+++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js
@@ -105,7 +105,7 @@ Object.defineProperty(this, "sync", {
if (arguments.length < 1 || arguments.length > 2 ) {
throw "sync(function [,object]) parameter count mismatch";
}
- return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj);
+ return Java.synchronized(func, syncobj);
}
});
@@ -160,7 +160,7 @@ Object.defineProperty(Object.prototype, "toSource", {
configurable: true, enumerable: false, writable: true,
value: function(state) {
if (! state) {
- state = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap());
+ state = java.util.Collections.newSetFromMap(new java.util.HashMap());
}
if (state.contains(this)) {
return "{}";
diff --git a/src/jdk/nashorn/internal/scripts/JO.java b/src/jdk/nashorn/internal/scripts/JO.java
index d6173918..e5346cb2 100644
--- a/src/jdk/nashorn/internal/scripts/JO.java
+++ b/src/jdk/nashorn/internal/scripts/JO.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.scripts;
+import jdk.nashorn.internal.codegen.SpillObjectCreator;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -63,6 +64,18 @@ public class JO extends ScriptObject {
}
/**
+ * Constructor that takes a pre-initialized spill pool. Used for
+ * by {@link SpillObjectCreator} for intializing object literals
+ *
+ * @param map property map
+ * @param primitiveSpill primitive spill pool
+ * @param objectSpill reference spill pool
+ */
+ public JO(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+ super(map, primitiveSpill, objectSpill);
+ }
+
+ /**
* A method handle of this method is passed to the ScriptFunction constructor.
*
* @param map the property map to use for allocatorMap
diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java
index 33e0afd7..58ab97c1 100644
--- a/src/jdk/nashorn/tools/Shell.java
+++ b/src/jdk/nashorn/tools/Shell.java
@@ -41,6 +41,7 @@ import java.util.Locale;
import java.util.ResourceBundle;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
@@ -178,7 +179,6 @@ public class Shell {
*
* @return null if there are problems with option parsing.
*/
- @SuppressWarnings("resource")
private static Context makeContext(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) {
final PrintStream pout = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
final PrintStream perr = err instanceof PrintStream ? (PrintStream) err : new PrintStream(err);
@@ -225,6 +225,7 @@ public class Shell {
/**
* Compiles the given script files in the command line
+ * This is called only when using the --compile-only flag
*
* @param context the nashorn context
* @param global the global scope
@@ -245,12 +246,21 @@ public class Shell {
// For each file on the command line.
for (final String fileName : files) {
- final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse();
+ final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, 0, context.getLogger(Parser.class)).parse();
if (errors.getNumberOfErrors() != 0) {
return COMPILATION_ERROR;
}
+ new Compiler(
+ context,
+ env,
+ null, //null - pass no code installer - this is compile only
+ functionNode.getSource(),
+ context.getErrorManager(),
+ env._strict | functionNode.isStrict()).
+ compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
+
if (env._print_ast) {
context.getErr().println(new ASTWriter(functionNode));
}
@@ -259,8 +269,9 @@ public class Shell {
context.getErr().println(new PrintVisitor(functionNode));
}
- //null - pass no code installer - this is compile only
- new Compiler(env).compile(functionNode);
+ if (errors.getNumberOfErrors() != 0) {
+ return COMPILATION_ERROR;
+ }
}
} finally {
env.getOut().flush();
@@ -390,7 +401,6 @@ public class Shell {
* @param global global scope object to use
* @return return code
*/
- @SuppressWarnings("resource")
private static int readEvalPrint(final Context context, final Global global) {
final String prompt = bundle.getString("shell.prompt");
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
@@ -436,19 +446,16 @@ public class Shell {
continue;
}
- Object res;
try {
- res = context.eval(global, source, global, "<shell>", env._strict);
+ final Object res = context.eval(global, source, global, "<shell>", env._strict);
+ if (res != ScriptRuntime.UNDEFINED) {
+ err.println(JSType.toString(res));
+ }
} catch (final Exception e) {
err.println(e);
if (env._dump_on_error) {
e.printStackTrace(err);
}
- continue;
- }
-
- if (res != ScriptRuntime.UNDEFINED) {
- err.println(JSType.toString(res));
}
}
} finally {
diff --git a/test/examples/apply_to_call_benchmark.js b/test/examples/apply_to_call_benchmark.js
new file mode 100644
index 00000000..bed80eca
--- /dev/null
+++ b/test/examples/apply_to_call_benchmark.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var Class = {
+ create: function() {
+ return function() { //vararg
+ this.initialize.apply(this, arguments);
+ }
+ }
+};
+
+Color = Class.create();
+Color.prototype = {
+ red: 0, green: 0, blue: 0,
+ initialize: function(r,g,b) {
+ this.red = r;
+ this.green = g;
+ this.blue = b;
+ }
+}
+
+function bench(x) {
+ var d = new Date;
+ var colors = new Array(16);
+ for (var i=0;i<1e8;i++) {
+ colors[i&0xf] = (new Color(1,2,3));
+ }
+ print(new Date - d);
+ return colors;
+}
+bench(17);
+
+print("Swapping out call");
+Function.prototype.call = function() {
+ throw "This should not happen, apply should be called instead";
+};
+
+bench(17);
+
+print("All done!");
diff --git a/test/examples/array-micro.js b/test/examples/array-micro.js
index 9bb898f6..1a7b1d6b 100644
--- a/test/examples/array-micro.js
+++ b/test/examples/array-micro.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/test/script/basic/ranges_payload.js b/test/examples/charcodeat-benchmark.js
index f10a4a28..308e2a07 100644
--- a/test/script/basic/ranges_payload.js
+++ b/test/examples/charcodeat-benchmark.js
@@ -1,74 +1,63 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @subtest
+ * Simple benchmark to measure charCodeAt specialized method performance
*/
-function f(c) {
- var v = c & 0xffff;
- var w = v & 0xfff;
- var x = v * w;
- return x;
-}
+var str = "sghjkdsfkjghsdfjkfkjdfkjdfjkdfjkfdjkfdkfldjfhdfpkjdhafgksdjfgldfgjldfkjgdlfjgldkfjgkldfj";
+var RESULT1 = 9187;
+var RESULT2 = 1496;
-function g() {
- var sum = 0;
- for (var x = 0; x < 4711; x++) {
- sum += x;
+function f() {
+ var len = str.length;
+ var c = 0;
+ for (var i = 0; i < len; i++) {
+ c += str.charCodeAt(i);
}
- return sum;
+ return c;
}
-function g2() {
+function bench(res) {
+ var d = new Date;
var sum = 0;
- //make sure we overflow
- var displacement = 0x7ffffffe;
- for (var x = displacement; x < (displacement + 2); x++) {
- sum += x;
+ for (var i = 0; i < 1e6; i++) {
+ sum |= f();
}
- return sum;
+ if (sum == res) {
+ print("Verified OK");
+ } else {
+ print("Verification failed " + sum + " should be " + res);
+ }
+ print((new Date - d) + " ms");
}
-//mostly provide code coverage for all the range operations
-function h() {
- var sum = 0;
- sum += 4711;
- sum &= 0xffff;
- sum /= 2;
- sum *= 2;
- sum -= 4;
- sum |= 2;
- sum ^= 17;
- sum = sum % 10000;
- sum = -sum;
- return sum
-}
+bench(RESULT1);
+
+print("Replacing charCodeAt... ");
+
+String.prototype.charCodeAt = function() { return 17; }
+
+bench(RESULT2);
-print(f(17));
-print(g());
-print(g2());
-print(h());
+print("Done");
diff --git a/test/examples/dual-fields-micro.js b/test/examples/dual-fields-micro.js
index aafc8888..b1aa5119 100644
--- a/test/examples/dual-fields-micro.js
+++ b/test/examples/dual-fields-micro.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -34,15 +34,15 @@ function b(x,y) {
}
var sum = 1;
-function bench() {
+function bench() {
var d = new Date;
for (var iter = 0; iter <4*50e6; iter++) {
- sum *= 20 * b(21,22);
+ sum *= 20 * b(21,22);
}
print("time = " +(new Date-d));
- print(sum);
+ print(sum);
}
bench();
diff --git a/test/examples/getter-setter-micro.js b/test/examples/getter-setter-micro.js
new file mode 100644
index 00000000..68ed1c30
--- /dev/null
+++ b/test/examples/getter-setter-micro.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * A micro-benchmark for getters and setters with primitive values,
+ * alternating between ints and doubles. Introduction of primitive
+ * and optimistic user accessors in JDK-8062401 make this faster by
+ * 10x or more by allowing inlining and other optimizations to take place.
+ */
+
+var x = {
+ get m() {
+ return this._m;
+ },
+ set m(v) {
+ this._m = v;
+ },
+ get n() {
+ return this._n;
+ },
+ set n(v) {
+ this._n = v;
+ }
+};
+
+
+function bench(v1, v2, result) {
+ var start = Date.now();
+ x.n = v1;
+ for (var i = 0; i < 1e8; i++) {
+ x.m = v2;
+ if (x.m + x.n !== result) {
+ throw "wrong result";
+ }
+ }
+ print("done in", Date.now() - start, "millis");
+}
+
+for (var i = 0; i < 10; i++) {
+ bench(i, 4, 4 + i);
+}
+
+for (var i = 0; i < 10; i++) {
+ bench(i, 4.5, 4.5 + i);
+}
+
+for (var i = 0; i < 10; i++) {
+ bench(i, 5, 5 + i);
+}
+
+for (var i = 0; i < 10; i++) {
+ bench(i, 5.5, 5.5 + i);
+}
diff --git a/test/examples/innerbench.js b/test/examples/innerbench.js
index b7be7416..3077075a 100644
--- a/test/examples/innerbench.js
+++ b/test/examples/innerbench.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/test/examples/int-micro.js b/test/examples/int-micro.js
index 82f4b099..0e2ec83b 100644
--- a/test/examples/int-micro.js
+++ b/test/examples/int-micro.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/test/examples/push-pop-benchmark.js b/test/examples/push-pop-benchmark.js
new file mode 100644
index 00000000..16f4c940
--- /dev/null
+++ b/test/examples/push-pop-benchmark.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Simple benchmark to measure push/pop specialized method performance
+ */
+
+var a = [];
+
+var RESULT = 15;
+
+function bench() {
+ var sum = 0;
+ for (var i=0;i<10;i++) {
+ a.push(i);
+ }
+ for (var i=0;i<10;i++) {
+ sum |= a.pop();
+ }
+ return sum;
+}
+
+function runbench() {
+ var sum = 0;
+ for (var iters = 0; iters<1e8; iters++) {
+ sum |= bench();
+ }
+ return sum;
+}
+
+var d = new Date;
+var res = runbench();
+print((new Date - d) + " ms");
+print();
+if (res != RESULT) {
+ print("ERROR: Wrong result - should be " + RESULT);
+} else {
+ print("Verified OK - result is correct");
+}
diff --git a/test/examples/string-micro.js b/test/examples/string-micro.js
index 56ed0ddb..8b2f5f38 100644
--- a/test/examples/string-micro.js
+++ b/test/examples/string-micro.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -46,12 +46,18 @@ bench("[]", function() {
str[2];
});
-bench("fromCharCode", function() {
+bench("fromCharCode 1", function() {
String.fromCharCode(97);
String.fromCharCode(98);
String.fromCharCode(99);
});
+bench("fromCharCode 2", function() {
+ String.fromCharCode(97, 98);
+ String.fromCharCode(97, 98, 99);
+ String.fromCharCode(97, 98, 99, 100);
+});
+
bench("charAt 1", function() {
str.charAt(0);
str.charAt(1);
diff --git a/test/examples/typechain.js b/test/examples/typechain.js
index 8b13ad97..90401a2f 100644
--- a/test/examples/typechain.js
+++ b/test/examples/typechain.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
diff --git a/test/lib/benchmark.js b/test/lib/benchmark.js
index e759cf11..67cd4fa6 100644
--- a/test/lib/benchmark.js
+++ b/test/lib/benchmark.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,14 +33,14 @@ var benchmark = function(method, timeInMillis, args) {
startTime = new Date,
runs = 0;
do {
- method.apply(args);
- runs++;
- totalTime = new Date - startTime;
+ method.apply(args);
+ runs++;
+ totalTime = new Date - startTime;
} while (totalTime < timeInMillis);
-
+
// convert ms to seconds
totalTime /= 1000;
-
+
// period → how long per operation
period = totalTime / runs;
diff --git a/test/opt/add.js b/test/opt/add.js
index 6e43ae0c..3e675713 100644
--- a/test/opt/add.js
+++ b/test/opt/add.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Example of an add function that gets specialized to doubles
- * if run with --optimize flag set
+ * if run with --optimize flag set
*/
function add(a,b) {
@@ -34,7 +34,7 @@ function add(a,b) {
function bench() {
var sum = 1;
for (var x = 0 ; x < 10e8/2 ; x ++) {
- sum *= add(x,x + 1);
+ sum *= add(x,x + 1);
}
return sum;
}
diff --git a/test/opt/add_constant.js b/test/opt/add_constant.js
index 0f2ae8b0..334ea0f9 100644
--- a/test/opt/add_constant.js
+++ b/test/opt/add_constant.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Example of an add function that gets specialized to doubles
- * if run with --optimize flag set
+ * if run with --optimize flag set
*/
function add(a,b) {
@@ -34,7 +34,7 @@ function add(a,b) {
function bench() {
var sum = 1;
for (var x = 0 ; x < 5e7 ; x++) {
- sum *= add(x, 17);
+ sum *= add(x, 17);
}
return sum;
}
diff --git a/test/opt/add_reuse_callsite.js b/test/opt/add_reuse_callsite.js
index 35398233..9d04e3f5 100644
--- a/test/opt/add_reuse_callsite.js
+++ b/test/opt/add_reuse_callsite.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Example of an add function that gets specialized to doubles
- * if run with --optimize flag set
+ * if run with --optimize flag set
*/
function add(a,b) {
@@ -34,10 +34,10 @@ function add(a,b) {
function bench() {
var sum = 1;
for (var x = 0 ; x < 5e7 ; x++) {
- sum *= add(x,x + 1);
+ sum *= add(x,x + 1);
}
for (var x = 0; x < 5e7 ; x++) {
- sum *= add(x + 2, x + 3);
+ sum *= add(x + 2, x + 3);
}
return sum;
}
diff --git a/test/opt/add_revert2.js b/test/opt/add_revert2.js
index 6ea36c5d..b7ea1bb6 100644
--- a/test/opt/add_revert2.js
+++ b/test/opt/add_revert2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Example of an add function that gets specialized to doubles
- * if run with --optimize flag set
+ * if run with --optimize flag set
*/
function add(a,b) {
@@ -34,8 +34,8 @@ function add(a,b) {
function bench() {
var sum = 1;
for (var x = 0 ; x < 5e7 ; x++) {
- sum *= add(x, 17);
- sum *= add(x, x); //can use same revert as 17?
+ sum *= add(x, 17);
+ sum *= add(x, x); //can use same revert as 17?
}
return sum;
}
diff --git a/test/opt/cascade_specialize.js b/test/opt/cascade_specialize.js
index 7b5d66c2..12e41f04 100644
--- a/test/opt/cascade_specialize.js
+++ b/test/opt/cascade_specialize.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,4 +37,4 @@ function test() {
}
test();
-
+
diff --git a/test/script/assert.js b/test/script/assert.js
index 3656f86c..9971d299 100644
--- a/test/script/assert.js
+++ b/test/script/assert.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,8 +28,8 @@
*/
// Assert is TestNG's Assert class
-Object.defineProperty(this, "Assert", {
- configuable: true,
+Object.defineProperty(this, "Assert", {
+ configurable: true,
enumerable: false,
writable: true,
value: Packages.org.testng.Assert
@@ -37,10 +37,10 @@ Object.defineProperty(this, "Assert", {
// fail function to call TestNG Assert.fail
Object.defineProperty(this, "fail", {
- configuable: true,
+ configurable: true,
enumerable: false,
writable: true,
- // 'error' is optional. if present it has to be
+ // 'error' is optional. if present it has to be
// an ECMAScript Error object or java Throwable object
value: function (message, error) {
var throwable = null;
@@ -63,7 +63,7 @@ Object.defineProperty(this, "fail", {
});
Object.defineProperty(this, "printError", {
- configuable: true,
+ configurable: true,
enumerable: false,
writable: true,
value: function (e) {
diff --git a/test/script/basic/8024180/global_var_delete.js b/test/script/basic/8024180/global_var_delete.js
index f099dd33..b1725fb1 100644
--- a/test/script/basic/8024180/global_var_delete.js
+++ b/test/script/basic/8024180/global_var_delete.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/8024180/global_var_shadow.js b/test/script/basic/8024180/global_var_shadow.js
index 5ba5f5e2..f43f21f7 100644
--- a/test/script/basic/8024180/global_var_shadow.js
+++ b/test/script/basic/8024180/global_var_shadow.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/8024180/scope_no_such_prop.js b/test/script/basic/8024180/scope_no_such_prop.js
index 5973c469..8813eb08 100644
--- a/test/script/basic/8024180/scope_no_such_prop.js
+++ b/test/script/basic/8024180/scope_no_such_prop.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/8024180/with_expr_prop_add.js b/test/script/basic/8024180/with_expr_prop_add.js
index 7c3b3a54..359b8299 100644
--- a/test/script/basic/8024180/with_expr_prop_add.js
+++ b/test/script/basic/8024180/with_expr_prop_add.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/8024180/with_expr_proto_prop_add.js b/test/script/basic/8024180/with_expr_proto_prop_add.js
index a6a17e70..ad582e90 100644
--- a/test/script/basic/8024180/with_expr_proto_prop_add.js
+++ b/test/script/basic/8024180/with_expr_proto_prop_add.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -42,7 +42,7 @@ function func() {
if (i == 0) {
p.x = "p.x";
}
- }
+ }
}
}
diff --git a/test/script/basic/8024180/with_java_object.js b/test/script/basic/8024180/with_java_object.js
index 32db2a5c..e50a6a32 100644
--- a/test/script/basic/8024180/with_java_object.js
+++ b/test/script/basic/8024180/with_java_object.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8005958.js b/test/script/basic/JDK-8005958.js
index e72ba09b..485283b9 100644
--- a/test/script/basic/JDK-8005958.js
+++ b/test/script/basic/JDK-8005958.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8005958 : invoking a function through INVOKESTATIC with more
+ * JDK-8005958 : invoking a function through INVOKESTATIC with more
* arguments than it declares resulted in malformed bytecode being
* generated.
*
diff --git a/test/script/basic/JDK-8006304.js b/test/script/basic/JDK-8006304.js
index f2d2c017..71fded14 100644
--- a/test/script/basic/JDK-8006304.js
+++ b/test/script/basic/JDK-8006304.js
@@ -1,26 +1,26 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+
/**
* JDK-8006304 : Remove pre-population of maps for constructor produced maps.
*
diff --git a/test/script/basic/JDK-8006337.js b/test/script/basic/JDK-8006337.js
index 21c469a2..189af272 100644
--- a/test/script/basic/JDK-8006337.js
+++ b/test/script/basic/JDK-8006337.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8006337 : Discarded arguments for INVOKESTATIC must still be
+ * JDK-8006337 : Discarded arguments for INVOKESTATIC must still be
* evaluated for side effects.
*
* @test
diff --git a/test/script/basic/JDK-8006529-b.js b/test/script/basic/JDK-8006529-b.js
index a7a6e3f3..4a63c620 100644
--- a/test/script/basic/JDK-8006529-b.js
+++ b/test/script/basic/JDK-8006529-b.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -62,4 +62,4 @@ var x = [B, C]
for(var i in x) {
print("Doing " + i)
new x[i]()
-} \ No newline at end of file
+}
diff --git a/test/script/basic/JDK-8006570.js b/test/script/basic/JDK-8006570.js
index 29dc7ab6..da7e8916 100644
--- a/test/script/basic/JDK-8006570.js
+++ b/test/script/basic/JDK-8006570.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -57,4 +57,4 @@ strict();
strict.call(null);
strict.call("foo");
strict.call(1);
-strict.call(true); \ No newline at end of file
+strict.call(true);
diff --git a/test/script/basic/JDK-8006852a.js b/test/script/basic/JDK-8006852a.js
index 7e706bd7..0c3ee40f 100644
--- a/test/script/basic/JDK-8006852a.js
+++ b/test/script/basic/JDK-8006852a.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,24 +27,24 @@
* @test
* @run
*/
-
-function Field(val){
- this.value = val;
-}
-var times = 0;
-
-Field.prototype = {
- get value(){
- print("GETTER!");
- return this._value;
- },
- set value(val){
- print("SETTER!");
- this._value = val + (++times);
- }
-};
-
-var f = new Field("test");
-print(f.value);
-f.value = "test2";
+
+function Field(val){
+ this.value = val;
+}
+var times = 0;
+
+Field.prototype = {
+ get value(){
+ print("GETTER!");
+ return this._value;
+ },
+ set value(val){
+ print("SETTER!");
+ this._value = val + (++times);
+ }
+};
+
+var f = new Field("test");
+print(f.value);
+f.value = "test2";
print(f.value);
diff --git a/test/script/basic/JDK-8006852b.js b/test/script/basic/JDK-8006852b.js
index 2d0c4b6d..d236bc77 100644
--- a/test/script/basic/JDK-8006852b.js
+++ b/test/script/basic/JDK-8006852b.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
function MyCons(arg) {
if (arg == 2) {
this.foo = 3;
diff --git a/test/script/basic/JDK-8006857.js b/test/script/basic/JDK-8006857.js
index c6514640..4f9e2c69 100644
--- a/test/script/basic/JDK-8006857.js
+++ b/test/script/basic/JDK-8006857.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8006983.js b/test/script/basic/JDK-8006983.js
index 2c126c41..af4233a1 100644
--- a/test/script/basic/JDK-8006983.js
+++ b/test/script/basic/JDK-8006983.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8006984.js b/test/script/basic/JDK-8006984.js
index 60702e36..19ccf096 100644
--- a/test/script/basic/JDK-8006984.js
+++ b/test/script/basic/JDK-8006984.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,22 +23,22 @@
/**
* findProperty on WithObject was not considering its object argument
- *
+ *
* @test
* @run
*/
-var guiPkgs = { JFrame: function() { print("created"); } };
+var guiPkgs = { JFrame: function() { print("created"); } };
-with (guiPkgs) {
- var main = function() {
+with (guiPkgs) {
+ var main = function() {
var frame; // <---- this local variable caused scope to be not set properly prior to fix
- function createFrame() {
- frame = new JFrame();
- }
+ function createFrame() {
+ frame = new JFrame();
+ }
- createFrame();
- }
-}
+ createFrame();
+ }
+}
main();
diff --git a/test/script/basic/JDK-8007060.js b/test/script/basic/JDK-8007060.js
index 699cecb1..9d9a6739 100644
--- a/test/script/basic/JDK-8007060.js
+++ b/test/script/basic/JDK-8007060.js
@@ -91,4 +91,4 @@ test("hello");
[1, 2, 3].filter(F, "hello");
[1, 2, 3].filter(F, 1);
[1, 2, 3].filter(F, {});
-[1, 2, 3].filter(F, "hello"); \ No newline at end of file
+[1, 2, 3].filter(F, "hello");
diff --git a/test/script/basic/JDK-8007140.js b/test/script/basic/JDK-8007140.js
index 28b41919..a9faa4fb 100644
--- a/test/script/basic/JDK-8007140.js
+++ b/test/script/basic/JDK-8007140.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8007215.js b/test/script/basic/JDK-8007215.js
index 0dbd7185..65b4d38d 100644
--- a/test/script/basic/JDK-8007215.js
+++ b/test/script/basic/JDK-8007215.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Varargs based on too many parameters broke. Regression test.
- *
+ *
* @test
* @run
*/
@@ -31,11 +31,11 @@
function f() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
- var a = arguments[i];
- sum += a;
+ var a = arguments[i];
+ sum += a;
}
return sum;
-}
+}
var res;
diff --git a/test/script/basic/JDK-8007460.js b/test/script/basic/JDK-8007460.js
index 7dc4c31f..37fd4340 100644
--- a/test/script/basic/JDK-8007460.js
+++ b/test/script/basic/JDK-8007460.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,4 +37,4 @@ function f(y) {
print(y)
print(arguments[0])
}
-f(2) \ No newline at end of file
+f(2)
diff --git a/test/script/basic/JDK-8007522.js b/test/script/basic/JDK-8007522.js
index 855d7d19..fca76964 100644
--- a/test/script/basic/JDK-8007522.js
+++ b/test/script/basic/JDK-8007522.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8007523.js b/test/script/basic/JDK-8007523.js
index 2a97ce28..a157faf1 100644
--- a/test/script/basic/JDK-8007523.js
+++ b/test/script/basic/JDK-8007523.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8007523: VerifyError on script that uses regular expression literals with ternary operator
+ * JDK-8007523: VerifyError on script that uses regular expression literals with ternary operator
*
* @test
* @run
diff --git a/test/script/basic/JDK-8007619.js b/test/script/basic/JDK-8007619.js
index 2c91f9cf..ca5b33f2 100644
--- a/test/script/basic/JDK-8007619.js
+++ b/test/script/basic/JDK-8007619.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,11 +37,11 @@ var match = emailPattern.exec(input);
while (match != null) {
print("Match = " + match);
print("RegExp.lastMatch = " + RegExp.lastMatch);
-
+
print("RegExp.$1 = " + RegExp.$1);
print("RegExp.$2 = " + RegExp.$2);
print("RegExp.$3 = " + RegExp.$3);
-
+
print("RegExp.lastParen = " + RegExp.lastParen)
print("RegExp.input = " + RegExp.input);
diff --git a/test/script/basic/JDK-8007990.js b/test/script/basic/JDK-8007990.js
index 7f4f7399..d5a41aa6 100644
--- a/test/script/basic/JDK-8007990.js
+++ b/test/script/basic/JDK-8007990.js
@@ -22,15 +22,15 @@
*/
/**
- * JDK-8007990: Access methods declared on public interfaces implemented by
+ * JDK-8007990: Access methods declared on public interfaces implemented by
* non-public classes
*
* @test
* @run
*/
-var p = new Packages.java.io.File("test/script/basic/JDK-8007990.js");
-var path = p.toPath();
-var basicView = Packages.java.nio.file.Files.getFileAttributeView(path, Packages.java.nio.file.attribute.BasicFileAttributeView.class);
+var p = new Packages.java.io.File("test/script/basic/JDK-8007990.js");
+var path = p.toPath();
+var basicView = Packages.java.nio.file.Files.getFileAttributeView(path, Packages.java.nio.file.attribute.BasicFileAttributeView.class);
// We just want to confirm we can access the readAttributes() function
print(basicView.readAttributes().directory);
diff --git a/test/script/basic/JDK-8008197.js b/test/script/basic/JDK-8008197.js
index e77a13a9..c19186cc 100644
--- a/test/script/basic/JDK-8008197.js
+++ b/test/script/basic/JDK-8008197.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,7 +33,7 @@ var m = new javax.script.ScriptEngineManager();
var e = m.getEngineByName("nashorn");
var obj = {
- func: function(str) {
+ func: function(str) {
return /hello/.exec(str);
}
};
diff --git a/test/script/basic/JDK-8008206.js b/test/script/basic/JDK-8008206.js
index be84f51b..757edabd 100644
--- a/test/script/basic/JDK-8008206.js
+++ b/test/script/basic/JDK-8008206.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,9 +28,9 @@
* @run
*/
-var x = 1;
+var x = 1;
-switch (x) {
- case foo = false, 1:
- print("ok");
-}
+switch (x) {
+ case foo = false, 1:
+ print("ok");
+}
diff --git a/test/script/basic/JDK-8008238.js b/test/script/basic/JDK-8008238.js
index f58ec20a..8dbf1f89 100644
--- a/test/script/basic/JDK-8008238.js
+++ b/test/script/basic/JDK-8008238.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8008554.js b/test/script/basic/JDK-8008554.js
index f8ec9587..a40a4b45 100644
--- a/test/script/basic/JDK-8008554.js
+++ b/test/script/basic/JDK-8008554.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8008814-3.js b/test/script/basic/JDK-8008814-3.js
index 87a9ebf4..da798024 100644
--- a/test/script/basic/JDK-8008814-3.js
+++ b/test/script/basic/JDK-8008814-3.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8008814-4.js b/test/script/basic/JDK-8008814-4.js
index baca0221..766fac1c 100644
--- a/test/script/basic/JDK-8008814-4.js
+++ b/test/script/basic/JDK-8008814-4.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8009553.js b/test/script/basic/JDK-8009553.js
index 3617f162..64693fde 100644
--- a/test/script/basic/JDK-8009553.js
+++ b/test/script/basic/JDK-8009553.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8009868.js b/test/script/basic/JDK-8009868.js
index ffbc8c21..f9aabca8 100644
--- a/test/script/basic/JDK-8009868.js
+++ b/test/script/basic/JDK-8009868.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8010709.js b/test/script/basic/JDK-8010709.js
index d2ec87ae..863a12ec 100644
--- a/test/script/basic/JDK-8010709.js
+++ b/test/script/basic/JDK-8010709.js
@@ -22,7 +22,7 @@
*/
/**
- * JDK-8010709 org on the top level doesn't resolve
+ * JDK-8010709 org on the top level doesn't resolve
*
* @test
* @run
diff --git a/test/script/basic/JDK-8010710.js b/test/script/basic/JDK-8010710.js
index aa6e61a9..04375c43 100644
--- a/test/script/basic/JDK-8010710.js
+++ b/test/script/basic/JDK-8010710.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,7 +26,7 @@
* as array index in self modifying assigns
*
* @test
- * @run
+ * @run
*/
function zero() {
return 0;
@@ -38,9 +38,9 @@ var b = [a, a];
print(b[zero() + 1][2 + a[0]] += 10);
//repro for NASHORN-258 that never made it
-function AddRoundKey() {
- var r=0;
- state[r][1] &= 17;
+function AddRoundKey() {
+ var r=0;
+ state[r][1] &= 17;
}
var srcFiles = [];
@@ -52,7 +52,7 @@ var added = '';
//this broke the javafx build system. verify it works
function bouncingBall() {
for (j=0; j<100; j++) {
- added += srcFiles[j];
+ added += srcFiles[j];
}
}
bouncingBall();
@@ -61,7 +61,7 @@ print(added);
//this is how they should have done it for speed, that works always, verify this too
function bouncingBall2() {
for (var k=0; k<100; k++) {
- added += srcFiles[k];
+ added += srcFiles[k];
}
}
bouncingBall2();
diff --git a/test/script/basic/JDK-8010720.js b/test/script/basic/JDK-8010720.js
index 1dddf22b..11d35b4a 100644
--- a/test/script/basic/JDK-8010720.js
+++ b/test/script/basic/JDK-8010720.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8010731.js b/test/script/basic/JDK-8010731.js
new file mode 100644
index 00000000..a7c7fb33
--- /dev/null
+++ b/test/script/basic/JDK-8010731.js
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8010731: Nashorn exposes internal symbols such as __callee__, __scope__ to scripts
+ *
+ * @test
+ * @run
+ */
+
+function checkCallee() {
+ var x = arguments[0]; // force __callee__ (renamed as :callee)
+
+ print(__callee__);
+}
+
+try {
+ checkCallee();
+ fail("Should have thrown ReferenceError for __callee__");
+} catch (e) {
+ if (! (e instanceof ReferenceError)) {
+ fail("ReferenceError expected, got " + e);
+ }
+}
+
+function checkScope() {
+ var x = 334;
+
+ function inner() {
+ var y = x * x; // force __scope__ (renamed as :scope")
+ print(__scope__);
+ }
+
+ inner();
+}
+
+try {
+ checkScope();
+ fail("Should have thrown ReferenceError for __scope__");
+} catch (e) {
+ if (! (e instanceof ReferenceError)) {
+ fail("ReferenceError expected, got " + e);
+ }
+}
diff --git a/test/script/basic/JDK-8010804.js b/test/script/basic/JDK-8010804.js
index 04e216ad..5d6d260e 100644
--- a/test/script/basic/JDK-8010804.js
+++ b/test/script/basic/JDK-8010804.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -83,4 +83,4 @@ print(x.slice(-Infinity, -Infinity).length);
var d = new Date();
d.setYear(Infinity);
-print(d); \ No newline at end of file
+print(d);
diff --git a/test/script/basic/JDK-8010946-privileged.js b/test/script/basic/JDK-8010946-privileged.js
index fc409f97..2e04f542 100644
--- a/test/script/basic/JDK-8010946-privileged.js
+++ b/test/script/basic/JDK-8010946-privileged.js
@@ -25,7 +25,7 @@
* JDK-8010946: AccessController.doPrivileged() doesn't work as expected.
* This is actually a broader issue of having Dynalink correctly handle
* caller-sensitive methods.
- *
+ *
* NOTE: This is not a standalone test file, it is loaded by JDK-801946.js
* @subtest
*/
diff --git a/test/script/basic/JDK-8010946.js b/test/script/basic/JDK-8010946.js
index 4f012427..290d60ea 100644
--- a/test/script/basic/JDK-8010946.js
+++ b/test/script/basic/JDK-8010946.js
@@ -34,7 +34,7 @@
load(__DIR__ + "JDK-8010946-privileged.js")
try {
- // This should fail, even though the code itself resides in the
+ // This should fail, even though the code itself resides in the
// privileged script, as we're invoking it without going through
// doPrivileged()
print("Attempting unprivileged execution...")
diff --git a/test/script/basic/JDK-8011023.js b/test/script/basic/JDK-8011023.js
index fbc2ca96..d0104623 100644
--- a/test/script/basic/JDK-8011023.js
+++ b/test/script/basic/JDK-8011023.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Round should be ecma compliant
*
* @test
- * @run
+ * @run
*/
print(1/Math.round(-0.5));
diff --git a/test/script/basic/JDK-8011209.js b/test/script/basic/JDK-8011209.js
index 9098dfaa..975347dc 100644
--- a/test/script/basic/JDK-8011209.js
+++ b/test/script/basic/JDK-8011209.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011237.js b/test/script/basic/JDK-8011237.js
index e9e521a4..2bb25856 100644
--- a/test/script/basic/JDK-8011237.js
+++ b/test/script/basic/JDK-8011237.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011274.js b/test/script/basic/JDK-8011274.js
index b483c3e0..c2a97322 100644
--- a/test/script/basic/JDK-8011274.js
+++ b/test/script/basic/JDK-8011274.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011357.js b/test/script/basic/JDK-8011357.js
index 40efec5d..147be0cb 100644
--- a/test/script/basic/JDK-8011357.js
+++ b/test/script/basic/JDK-8011357.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011362.js b/test/script/basic/JDK-8011362.js
index bda4851a..c52edd65 100644
--- a/test/script/basic/JDK-8011362.js
+++ b/test/script/basic/JDK-8011362.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011365.js b/test/script/basic/JDK-8011365.js
index 30802576..cbec8b63 100644
--- a/test/script/basic/JDK-8011365.js
+++ b/test/script/basic/JDK-8011365.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
try {
Array.prototype.join.call(null, { toString:function() { throw 2 } });
- fail("should have thrown TypeError");
+ fail("should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
fail("TypeError expected, got " + e);
@@ -46,7 +46,7 @@ for (var n in names) {
if (funcName == "constructor") {
continue;
}
-
+
var prop = Array.prototype[funcName];
if (prop instanceof Function) {
// try 'null' this
diff --git a/test/script/basic/JDK-8011382.js b/test/script/basic/JDK-8011382.js
index 13b3a771..0c06b5b4 100644
--- a/test/script/basic/JDK-8011382.js
+++ b/test/script/basic/JDK-8011382.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8011382: Data prototype methods and constructor do not call user defined toISOString, valueOf methods per spec.
+ * JDK-8011382: Data prototype methods and constructor do not call user defined toISOString, valueOf methods per spec.
*
* @test
* @run
diff --git a/test/script/basic/JDK-8011394.js b/test/script/basic/JDK-8011394.js
index 070f5d3c..97ca915e 100644
--- a/test/script/basic/JDK-8011394.js
+++ b/test/script/basic/JDK-8011394.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011552.js b/test/script/basic/JDK-8011552.js
index f0735a00..4fa6137b 100644
--- a/test/script/basic/JDK-8011552.js
+++ b/test/script/basic/JDK-8011552.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011555.js b/test/script/basic/JDK-8011555.js
index c65ad612..c4b58e6b 100644
--- a/test/script/basic/JDK-8011555.js
+++ b/test/script/basic/JDK-8011555.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -35,7 +35,7 @@ with(new JavaImporter()) {
} catch(e) {
// We expect to get a TypeError for trying to use __noSuchMethod__ as
// a constructor. Before we fixed this bug, we were getting a runtime
- // exception with MH type mismatch on a MH.foldArguments within the
+ // exception with MH type mismatch on a MH.foldArguments within the
// WithObject code instead.
print(e)
}
diff --git a/test/script/basic/JDK-8011578.js b/test/script/basic/JDK-8011578.js
index 9a2f7438..ef8fa62b 100644
--- a/test/script/basic/JDK-8011578.js
+++ b/test/script/basic/JDK-8011578.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011718.js b/test/script/basic/JDK-8011718.js
index 7cb24f24..0c2fc8dc 100644
--- a/test/script/basic/JDK-8011718.js
+++ b/test/script/basic/JDK-8011718.js
@@ -28,19 +28,19 @@
* @run
*/
-var obj = {
- hello:"From obj",
-};
-var obj2 = {
- hello:"From obj2",
-};
+var obj = {
+ hello:"From obj",
+};
+var obj2 = {
+ hello:"From obj2",
+};
-function doit(cb){
- cb();
- var cb2 = cb.bind(obj2, "This one is not acccepted");
- cb2();
-}
+function doit(cb){
+ cb();
+ var cb2 = cb.bind(obj2, "This one is not acccepted");
+ cb2();
+}
-doit(function(){
- print(this.hello);
+doit(function(){
+ print(this.hello);
}.bind(obj));
diff --git a/test/script/basic/JDK-8011756.js b/test/script/basic/JDK-8011756.js
index c0e8d834..30810482 100644
--- a/test/script/basic/JDK-8011756.js
+++ b/test/script/basic/JDK-8011756.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011893.js b/test/script/basic/JDK-8011893.js
index 28382d2f..7c93924e 100644
--- a/test/script/basic/JDK-8011893.js
+++ b/test/script/basic/JDK-8011893.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011960.js b/test/script/basic/JDK-8011960.js
index f691d2c8..508b0b62 100644
--- a/test/script/basic/JDK-8011960.js
+++ b/test/script/basic/JDK-8011960.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011964.js b/test/script/basic/JDK-8011964.js
index a46023eb..ad010ac8 100644
--- a/test/script/basic/JDK-8011964.js
+++ b/test/script/basic/JDK-8011964.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8011974.js b/test/script/basic/JDK-8011974.js
index f3f9b4ae..c8f791cf 100644
--- a/test/script/basic/JDK-8011974.js
+++ b/test/script/basic/JDK-8011974.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8012083.js b/test/script/basic/JDK-8012083.js
index e782ff53..ae828f18 100644
--- a/test/script/basic/JDK-8012083.js
+++ b/test/script/basic/JDK-8012083.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8012093 - array literals can only be subject to constant evaluation under very special
+ * JDK-8012083 - array literals can only be subject to constant evaluation under very special
* circumstances.
*
* @test
diff --git a/test/script/basic/JDK-8012164.js b/test/script/basic/JDK-8012164.js
index 62bb09c4..4d0ed45b 100644
--- a/test/script/basic/JDK-8012164.js
+++ b/test/script/basic/JDK-8012164.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -46,11 +46,11 @@ function error() {
func();
-// See JDK-8015855: test/script/basic/JDK-8012164.js fails on Windows
+// See JDK-8015855: test/script/basic/JDK-8012164.js fails on Windows
// Replace '\' to '/' in class and file names of StackFrameElement objects
function printFrame(stack) {
var fileName = stack.fileName.replace(/\\/g, '/');
var className = stack.className.replace(/\\/g, '/');
print(className + '.' + stack.methodName + '(' +
- fileName + ':' + stack.lineNumber + ')');
+ fileName + ':' + stack.lineNumber + ')');
}
diff --git a/test/script/basic/JDK-8012191.js b/test/script/basic/JDK-8012191.js
index 8d1d2848..1bc0b348 100644
--- a/test/script/basic/JDK-8012191.js
+++ b/test/script/basic/JDK-8012191.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-// ClassCastException: Cannot cast java.lang.String to [Ljava.lang.Object;
+// ClassCastException: Cannot cast java.lang.String to [Ljava.lang.Object;
__noSuchProperty__ = function() {
print("obj.__noSuchProperty__ invoked for " + arguments[0]);
}
diff --git a/test/script/basic/JDK-8012240.js b/test/script/basic/JDK-8012240.js
index 2ac6eaf7..4128eeba 100644
--- a/test/script/basic/JDK-8012240.js
+++ b/test/script/basic/JDK-8012240.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,15 +33,15 @@ var in_getter_for_0 = false;
try {
Array.prototype.map.call(
{
- length: -1,
+ length: -1,
get 0() {
in_getter_for_0 = true;
throw 0;
}
- },
+ },
function(){}).length;
} catch (e) {
if (e !== 0 || !in_getter_for_0) {
fail("should have thrown error from getter for '0'th element");
}
-}
+}
diff --git a/test/script/basic/JDK-8012291.js b/test/script/basic/JDK-8012291.js
index b902df47..93f1250c 100644
--- a/test/script/basic/JDK-8012291.js
+++ b/test/script/basic/JDK-8012291.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8012305.js b/test/script/basic/JDK-8012305.js
index d08502de..211a809c 100644
--- a/test/script/basic/JDK-8012305.js
+++ b/test/script/basic/JDK-8012305.js
@@ -22,7 +22,7 @@
*/
/**
- * JDK-8012305: Function.bind can't be called on prototype function inside constructor
+ * JDK-8012305: Function.bind can't be called on prototype function inside constructor
*
* @test
* @run
@@ -36,4 +36,4 @@ function MyObject() {
MyObject.prototype._process = function() { print("Message "); }
-var s = new MyObject();
+var s = new MyObject();
diff --git a/test/script/basic/JDK-8012457.js b/test/script/basic/JDK-8012457.js
index 2f71a9a9..e7d46655 100644
--- a/test/script/basic/JDK-8012457.js
+++ b/test/script/basic/JDK-8012457.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -35,7 +35,7 @@ Function().apply(null, {length: 0.1})
// getter should be called
var getter_0_called = false;
-Function().apply(null,
+Function().apply(null,
Object.defineProperty([],"0",
{ get: function(){ getter_0_called = true; return 0 }
})
diff --git a/test/script/basic/JDK-8012462.js b/test/script/basic/JDK-8012462.js
index 4e015a99..1c7a16eb 100644
--- a/test/script/basic/JDK-8012462.js
+++ b/test/script/basic/JDK-8012462.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013131.js b/test/script/basic/JDK-8013131.js
index dfff8ac6..c7496b04 100644
--- a/test/script/basic/JDK-8013131.js
+++ b/test/script/basic/JDK-8013131.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013167.js b/test/script/basic/JDK-8013167.js
index ec3c71a1..6988183e 100644
--- a/test/script/basic/JDK-8013167.js
+++ b/test/script/basic/JDK-8013167.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,4 +29,4 @@
*/
var x = new Packages.jdk.nashorn.test.models.VarArgConstructor(1, false, "a", "b", "c")
-print(x.indicator) \ No newline at end of file
+print(x.indicator)
diff --git a/test/script/basic/JDK-8013325.js b/test/script/basic/JDK-8013325.js
index e1faa7b7..70e9fcb5 100644
--- a/test/script/basic/JDK-8013325.js
+++ b/test/script/basic/JDK-8013325.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,9 +33,9 @@ function x() {
// x doesn't see an arguments object as it has a nested function with that name
// so it'll invoke the function.
arguments("a", "b", "c");
-
+
function arguments(x, y, z) {
- // The function 'arguments' OTOH can't see itself; if it uses the
+ // The function 'arguments' OTOH can't see itself; if it uses the
// identifier 'arguments', it'll see its own arguments object.
print(arguments)
print(x + " " + y + " " + z)
diff --git a/test/script/basic/JDK-8013337.js b/test/script/basic/JDK-8013337.js
index b95da8bd..00ed4907 100644
--- a/test/script/basic/JDK-8013337.js
+++ b/test/script/basic/JDK-8013337.js
@@ -22,7 +22,7 @@
*/
/**
- * JDK-8013337: Issues with Date.prototype's get, set functions
+ * JDK-8013337: Issues with Date.prototype's get, set functions
*
* @test
* @option -timezone=Asia/Calcutta
@@ -63,7 +63,7 @@ checkGetterCalled("setMonth");
checkGetterCalled("setUTCMonth");
try {
- Date.prototype.setTime.call({}, { valueOf: function() { throw "err" } })
+ Date.prototype.setTime.call({}, { valueOf: function() { throw "err" } })
} catch (e) {
if (! (e instanceof TypeError)) {
fail("TypeError expected, got " + e);
diff --git a/test/script/basic/JDK-8013444.js b/test/script/basic/JDK-8013444.js
index 166575cd..0f3c19e3 100644
--- a/test/script/basic/JDK-8013444.js
+++ b/test/script/basic/JDK-8013444.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,14 +32,14 @@
var type = typeof JSON.parse('{}',function(){})
print("type is " + type);
-var obj = JSON.parse('{"name": "nashorn"}',
+var obj = JSON.parse('{"name": "nashorn"}',
function(k, v) {
if (k === "") return v;
return v.toUpperCase();
});
print(JSON.stringify(obj))
-var array =
+var array =
JSON.parse("[1, 3, 5, 7, 9, 11]",
function(k, v) {
if (k === "") return v;
diff --git a/test/script/basic/JDK-8013729.js b/test/script/basic/JDK-8013729.js
index a500602a..d4397f36 100644
--- a/test/script/basic/JDK-8013729.js
+++ b/test/script/basic/JDK-8013729.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013873.js b/test/script/basic/JDK-8013873.js
index dcae75cc..212c087d 100644
--- a/test/script/basic/JDK-8013873.js
+++ b/test/script/basic/JDK-8013873.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013874.js b/test/script/basic/JDK-8013874.js
index 4b02b92b..32dbcf7f 100644
--- a/test/script/basic/JDK-8013874.js
+++ b/test/script/basic/JDK-8013874.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013878.js b/test/script/basic/JDK-8013878.js
index 81e39f91..d00ebd30 100644
--- a/test/script/basic/JDK-8013878.js
+++ b/test/script/basic/JDK-8013878.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8013919.js b/test/script/basic/JDK-8013919.js
index bd25dc12..b986dc56 100644
--- a/test/script/basic/JDK-8013919.js
+++ b/test/script/basic/JDK-8013919.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,7 +33,7 @@ try {
print("a");
} finally {
var b = function() {
- print("b");
+ print("b");
}
b();
}
diff --git a/test/script/basic/JDK-8014426.js b/test/script/basic/JDK-8014426.js
index 220aa7f3..f32989e0 100644
--- a/test/script/basic/JDK-8014426.js
+++ b/test/script/basic/JDK-8014426.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8014647.js b/test/script/basic/JDK-8014647.js
index 8d06848f..ec76e1f3 100644
--- a/test/script/basic/JDK-8014647.js
+++ b/test/script/basic/JDK-8014647.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8014781.js b/test/script/basic/JDK-8014781.js
index 3c6d7d88..72732a81 100644
--- a/test/script/basic/JDK-8014781.js
+++ b/test/script/basic/JDK-8014781.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8014785.js b/test/script/basic/JDK-8014785.js
index 27b05bd1..5bb0a25a 100644
--- a/test/script/basic/JDK-8014785.js
+++ b/test/script/basic/JDK-8014785.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -40,7 +40,7 @@ print("foo.x = " + foo.x); // prints obj.x which is 34
// update obj.x via foo.x
foo.x = "hello";
print("obj.x = " + obj.x); // prints "hello" now
-
+
obj.x = 42; // foo.x also becomes 42
print("obj.x = " + obj.x); // prints 42
print("foo.x = " + foo.x); // prints 42
diff --git a/test/script/basic/JDK-8014953.js b/test/script/basic/JDK-8014953.js
index ba7cef0f..06b74af4 100644
--- a/test/script/basic/JDK-8014953.js
+++ b/test/script/basic/JDK-8014953.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
try {
new java.util.ArrrayList(16)
} catch(e) {
diff --git a/test/script/basic/JDK-8015267.js b/test/script/basic/JDK-8015267.js
index b7c1f9bf..74fac2aa 100644
--- a/test/script/basic/JDK-8015267.js
+++ b/test/script/basic/JDK-8015267.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
var a = ['a', 'b', 'c', 'd']
var l = Java.to(a, java.util.List)
@@ -64,10 +64,10 @@ print(a)
l[7] = 'g'
print(a)
-try { l.add(15, '') } catch(e) { print(e.class) }
-try { l.remove(15) } catch(e) { print(e.class) }
-try { l.add(-1, '') } catch(e) { print(e.class) }
-try { l.remove(-1) } catch(e) { print(e.class) }
+try { l.add(15, '') } catch(e) { print(e.class) }
+try { l.remove(15) } catch(e) { print(e.class) }
+try { l.add(-1, '') } catch(e) { print(e.class) }
+try { l.remove(-1) } catch(e) { print(e.class) }
l.remove(7)
l.remove(2)
diff --git a/test/script/basic/JDK-8015345.js b/test/script/basic/JDK-8015345.js
index 3f551d9e..938d9c9d 100644
--- a/test/script/basic/JDK-8015345.js
+++ b/test/script/basic/JDK-8015345.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015346.js b/test/script/basic/JDK-8015346.js
index 2365cc82..271ebbac 100644
--- a/test/script/basic/JDK-8015346.js
+++ b/test/script/basic/JDK-8015346.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015347.js b/test/script/basic/JDK-8015347.js
index d5a8ba31..7b1898cc 100644
--- a/test/script/basic/JDK-8015347.js
+++ b/test/script/basic/JDK-8015347.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015348.js b/test/script/basic/JDK-8015348.js
index 77ff6031..46e30f31 100644
--- a/test/script/basic/JDK-8015348.js
+++ b/test/script/basic/JDK-8015348.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015349.js b/test/script/basic/JDK-8015349.js
index 7588a651..e91b13ef 100644
--- a/test/script/basic/JDK-8015349.js
+++ b/test/script/basic/JDK-8015349.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@ function printEval(code) {
print(code + " = " + eval(code));
}
-printEval("'abc'.lastIndexOf('a', 4)");
+printEval("'abc'.lastIndexOf('a', 4)");
printEval("'abc'.lastIndexOf('b', Infinity)");
printEval("'abc'.lastIndexOf('a', -1)");
printEval("'abc'.lastIndexOf('a', -Infinity)");
diff --git a/test/script/basic/JDK-8015350.js b/test/script/basic/JDK-8015350.js
index c8202969..62c97960 100644
--- a/test/script/basic/JDK-8015350.js
+++ b/test/script/basic/JDK-8015350.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015352.js b/test/script/basic/JDK-8015352.js
index b40e6461..ecb54f5d 100644
--- a/test/script/basic/JDK-8015352.js
+++ b/test/script/basic/JDK-8015352.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015353.js b/test/script/basic/JDK-8015353.js
index a9baa469..2b101a01 100644
--- a/test/script/basic/JDK-8015353.js
+++ b/test/script/basic/JDK-8015353.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015354.js b/test/script/basic/JDK-8015354.js
index 3cbe676e..80fa9cf2 100644
--- a/test/script/basic/JDK-8015354.js
+++ b/test/script/basic/JDK-8015354.js
@@ -22,7 +22,7 @@
*/
/**
- * JDK-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead
+ * JDK-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead
*
* @test
* @run
diff --git a/test/script/basic/JDK-8015355.js b/test/script/basic/JDK-8015355.js
index aa1a39de..f5176ecb 100644
--- a/test/script/basic/JDK-8015355.js
+++ b/test/script/basic/JDK-8015355.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* JDK-8015355: Array.prototype functions don't honour non-writable length and / or index properties
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/JDK-8015356.js b/test/script/basic/JDK-8015356.js
index edc77c0c..60bb1469 100644
--- a/test/script/basic/JDK-8015356.js
+++ b/test/script/basic/JDK-8015356.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* JDK-8015355: Array concatenation should ignore empty array elements.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/JDK-8015357.js b/test/script/basic/JDK-8015357.js
index b6c94537..325c5711 100644
--- a/test/script/basic/JDK-8015357.js
+++ b/test/script/basic/JDK-8015357.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,8 +28,8 @@
* @run
*/
-var a = [];
-a[0x7fffffff]=1;
+var a = [];
+a[0x7fffffff]=1;
if (a.sort()[0] != 1) {
fail("a.sort()[0] != 1");
diff --git a/test/script/basic/JDK-8015741.js b/test/script/basic/JDK-8015741.js
index fdecee26..61b39398 100644
--- a/test/script/basic/JDK-8015741.js
+++ b/test/script/basic/JDK-8015741.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015830.js b/test/script/basic/JDK-8015830.js
index 314a73a4..90132f9c 100644
--- a/test/script/basic/JDK-8015830.js
+++ b/test/script/basic/JDK-8015830.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015892.js b/test/script/basic/JDK-8015892.js
index a6ab4c8b..9c531593 100644
--- a/test/script/basic/JDK-8015892.js
+++ b/test/script/basic/JDK-8015892.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,10 +29,10 @@
* @run
*/
-function doIt() {
- if (something) {
- x = x.obj;
- } else {
- var x = "x";
- }
-}
+function doIt() {
+ if (something) {
+ x = x.obj;
+ } else {
+ var x = "x";
+ }
+}
diff --git a/test/script/basic/JDK-8015945.js b/test/script/basic/JDK-8015945.js
index 5b9962e5..e97965bd 100644
--- a/test/script/basic/JDK-8015945.js
+++ b/test/script/basic/JDK-8015945.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015959.js b/test/script/basic/JDK-8015959.js
index c5322e3e..40567370 100644
--- a/test/script/basic/JDK-8015959.js
+++ b/test/script/basic/JDK-8015959.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8015969.js b/test/script/basic/JDK-8015969.js
index a9813773..57c6e1fc 100644
--- a/test/script/basic/JDK-8015969.js
+++ b/test/script/basic/JDK-8015969.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,43 +32,26 @@
var m = new javax.script.ScriptEngineManager();
var e = m.getEngineByName("nashorn");
+e.put("fail", fail);
e.eval(<<EOF
'use strict';
try {
- context = 444;
- print("FAILED!! context write should have thrown error");
-} catch (e) {
- if (! (e instanceof TypeError)) {
- print("TypeError expected but got " + e);
- }
-}
-
-try {
- engine = "hello";
- print("FAILED!! engine write should have thrown error");
-} catch (e) {
- if (! (e instanceof TypeError)) {
- print("TypeError expected but got " + e);
- }
-}
-
-try {
delete context;
- print("FAILED!! context delete should have thrown error");
+ fail("FAILED!! context delete should have thrown error");
} catch (e) {
if (! (e instanceof SyntaxError)) {
- print("SyntaxError expected but got " + e);
+ fail("SyntaxError expected but got " + e);
}
}
try {
delete engine;
- print("FAILED!! engine delete should have thrown error");
+ fail("FAILED!! engine delete should have thrown error");
} catch (e) {
if (! (e instanceof SyntaxError)) {
- print("SyntaxError expected but got " + e);
+ fail("SyntaxError expected but got " + e);
}
}
diff --git a/test/script/basic/JDK-8016235.js b/test/script/basic/JDK-8016235.js
index 3945f8fd..9ac999ca 100644
--- a/test/script/basic/JDK-8016235.js
+++ b/test/script/basic/JDK-8016235.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,27 +23,27 @@
/**
* JDK-8016235 : use before definition in catch block generated erroneous bytecode
- * as there is no guarantee anything in the try block has executed.
+ * as there is no guarantee anything in the try block has executed.
*
* @test
- * @run
+ * @run
*/
function f() {
try {
- var parser = {};
+ var parser = {};
} catch (e) {
- parser = parser.context();
+ parser = parser.context();
}
}
-function g() {
+function g() {
try {
return "apa";
} catch (tmp) {
- //for now, too conservative as var ex declaration exists on the function
- //level, but at least the code does not break, and the analysis is driven
- //from the catch block (the rare case), not the try block (the common case)
+ //for now, too conservative as var ex declaration exists on the function
+ //level, but at least the code does not break, and the analysis is driven
+ //from the catch block (the rare case), not the try block (the common case)
var ex = new Error("DOM Exception 5");
ex.code = ex.number = 5;
return ex;
diff --git a/test/script/basic/JDK-8016239.js b/test/script/basic/JDK-8016239.js
index 84849ae4..119851cb 100644
--- a/test/script/basic/JDK-8016239.js
+++ b/test/script/basic/JDK-8016239.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8016518.js b/test/script/basic/JDK-8016518.js
index a468483a..e31d7588 100644
--- a/test/script/basic/JDK-8016518.js
+++ b/test/script/basic/JDK-8016518.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8016542.js b/test/script/basic/JDK-8016542.js
index 6aeae264..5b8987f8 100644
--- a/test/script/basic/JDK-8016542.js
+++ b/test/script/basic/JDK-8016542.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8016618.js b/test/script/basic/JDK-8016618.js
index 1b35db76..0db20a08 100644
--- a/test/script/basic/JDK-8016618.js
+++ b/test/script/basic/JDK-8016618.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -38,7 +38,7 @@ var x = 33;
function func(x, y) {
print('func.x = ' + x);
print('func.x = ' + y)
-};
+};
var obj = {
foo: 'hello',
@@ -54,18 +54,30 @@ EOF
});
// load on mirror with local object as argument
-global.load({
+global.load({
name: "code",
script: "print('x = ' + x)"
});
function f() {
// mirror function called with local arguments
+ // global.func.apply(obj, arguments);
global.func.apply(obj, arguments);
}
f(23, "hello");
+f(24, "hello2");
+
+var oldCall = Function.prototype.call;
+Function.prototype.call = function() {
+ throw "this should never happen! go back to apply!";
+};
+
+f(25, "hello3");
+
+Function.prototype.call = oldCall;
+
var fObject = global.eval("Object");
// instanceof on mirrors
diff --git a/test/script/basic/JDK-8016618.js.EXPECTED b/test/script/basic/JDK-8016618.js.EXPECTED
index fe260ba9..4fc92102 100644
--- a/test/script/basic/JDK-8016618.js.EXPECTED
+++ b/test/script/basic/JDK-8016618.js.EXPECTED
@@ -1,6 +1,10 @@
x = 33
func.x = 23
func.x = hello
+func.x = 24
+func.x = hello2
+func.x = 25
+func.x = hello3
global instanceof fObject? true
x is wriable ? true
x value = 33
diff --git a/test/script/basic/JDK-8016667.js b/test/script/basic/JDK-8016667.js
index 169a8f35..831de47b 100644
--- a/test/script/basic/JDK-8016667.js
+++ b/test/script/basic/JDK-8016667.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,22 +31,22 @@
function toto() {
var friends = 1;
(joe = friends) == null;
-}
+}
//JDK-8019476 duplicate case of this
-Function("with(\nnull == (this % {}))( /x/g );");
+Function("with(\nnull == (this % {}))( /x/g );");
function f() {
with(null == (this % {}))(/x/g);
}
-Function("return (null != [,,] <= this);");
+Function("return (null != [,,] <= this);");
function f2() {
return (null != [,,] <= this);
}
-Function("/*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }");
+Function("/*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }");
function f3() {
/*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }
diff --git a/test/script/basic/JDK-8016681.js b/test/script/basic/JDK-8016681.js
index 9596b0dd..2c93b7c6 100644
--- a/test/script/basic/JDK-8016681.js
+++ b/test/script/basic/JDK-8016681.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8017046.js b/test/script/basic/JDK-8017046.js
index 7097e9f5..be3261c8 100644
--- a/test/script/basic/JDK-8017046.js
+++ b/test/script/basic/JDK-8017046.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8017082.js b/test/script/basic/JDK-8017082.js
index 5ac96324..3b7934fa 100644
--- a/test/script/basic/JDK-8017082.js
+++ b/test/script/basic/JDK-8017082.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8017084.js b/test/script/basic/JDK-8017084.js
index ceac68ee..1c3bf8b5 100644
--- a/test/script/basic/JDK-8017084.js
+++ b/test/script/basic/JDK-8017084.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8017768.js b/test/script/basic/JDK-8017768.js
index c91f6d1f..2f232675 100644
--- a/test/script/basic/JDK-8017768.js
+++ b/test/script/basic/JDK-8017768.js
@@ -23,7 +23,7 @@
/**
* JDK-8017768: Allow use of dot notation for inner class names.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/JDK-8017950.js b/test/script/basic/JDK-8017950.js
index c84eacc5..3684cfbc 100644
--- a/test/script/basic/JDK-8017950.js
+++ b/test/script/basic/JDK-8017950.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -36,7 +36,7 @@ function func() {
}
}
-function f() {
+function f() {
func()
}
diff --git a/test/script/basic/JDK-8019226.js b/test/script/basic/JDK-8019226.js
index 3a1cf2f9..6c0f374e 100644
--- a/test/script/basic/JDK-8019226.js
+++ b/test/script/basic/JDK-8019226.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8019226: line number not generated for first statement if it is on the same function declaration line
+ * JDK-8019226: line number not generated for first statement if it is on the same function declaration line
*
* @test
* @run
diff --git a/test/script/basic/JDK-8019473.js b/test/script/basic/JDK-8019473.js
index 5001f3d7..f13375f3 100644
--- a/test/script/basic/JDK-8019473.js
+++ b/test/script/basic/JDK-8019473.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019478.js b/test/script/basic/JDK-8019478.js
index f5e2a645..3736ea8f 100644
--- a/test/script/basic/JDK-8019478.js
+++ b/test/script/basic/JDK-8019478.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019482.js b/test/script/basic/JDK-8019482.js
index 09f91e42..f9061d8e 100644
--- a/test/script/basic/JDK-8019482.js
+++ b/test/script/basic/JDK-8019482.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019488.js b/test/script/basic/JDK-8019488.js
index 0cb58e90..1a4a5369 100644
--- a/test/script/basic/JDK-8019488.js
+++ b/test/script/basic/JDK-8019488.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019508.js b/test/script/basic/JDK-8019508.js
index 88ecbec3..cfd80801 100644
--- a/test/script/basic/JDK-8019508.js
+++ b/test/script/basic/JDK-8019508.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019553.js b/test/script/basic/JDK-8019553.js
index bec3a528..a9d84af2 100644
--- a/test/script/basic/JDK-8019553.js
+++ b/test/script/basic/JDK-8019553.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019585.js b/test/script/basic/JDK-8019585.js
index 58d18f35..235e6945 100644
--- a/test/script/basic/JDK-8019585.js
+++ b/test/script/basic/JDK-8019585.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,5 +30,5 @@
*/
function f() {
- var a = b == 17 && (a = toto(b)) && toto2(a);
+ var a = b == 17 && (a = toto(b)) && toto2(a);
}
diff --git a/test/script/basic/JDK-8019629.js b/test/script/basic/JDK-8019629.js
index 2d284d05..643bd61f 100644
--- a/test/script/basic/JDK-8019629.js
+++ b/test/script/basic/JDK-8019629.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8019629: void operator should always evaluate to undefined
+ * JDK-8019629: void operator should always evaluate to undefined
*
* @test
* @run
diff --git a/test/script/basic/JDK-8019783.js b/test/script/basic/JDK-8019783.js
index 27afcaf2..b9fcbd8d 100644
--- a/test/script/basic/JDK-8019783.js
+++ b/test/script/basic/JDK-8019783.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019791.js b/test/script/basic/JDK-8019791.js
index ad32ce3c..feda5559 100644
--- a/test/script/basic/JDK-8019791.js
+++ b/test/script/basic/JDK-8019791.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019805.js b/test/script/basic/JDK-8019805.js
index 7e3e25b5..a8423b3e 100644
--- a/test/script/basic/JDK-8019805.js
+++ b/test/script/basic/JDK-8019805.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019808.js b/test/script/basic/JDK-8019808.js
index 08d090cf..2584ab4e 100644
--- a/test/script/basic/JDK-8019808.js
+++ b/test/script/basic/JDK-8019808.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-Function("switch([]) { case 7: }");
+Function("switch([]) { case 7: }");
function f() {
switch([]) {
diff --git a/test/script/basic/JDK-8019809.js b/test/script/basic/JDK-8019809.js
index cc31bd86..ae1a9e0c 100644
--- a/test/script/basic/JDK-8019809.js
+++ b/test/script/basic/JDK-8019809.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-//Function("L: {break L;return; }");
+//Function("L: {break L;return; }");
function f() {
L: { break L; return; }
diff --git a/test/script/basic/JDK-8019810.js b/test/script/basic/JDK-8019810.js
index a22fb06f..5ee1fab9 100644
--- a/test/script/basic/JDK-8019810.js
+++ b/test/script/basic/JDK-8019810.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019811.js b/test/script/basic/JDK-8019811.js
index e64fafb3..b72f9bc2 100644
--- a/test/script/basic/JDK-8019811.js
+++ b/test/script/basic/JDK-8019811.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,18 +30,18 @@
function f(x) {
var window = 17;
- return function (x) {
- return true
+ return function (x) {
+ return true
} (x) >> window;
}
-Function("L:if((function x ()3)() + arguments++) {return; } else if (new gc()) while(((x2.prop = functional)) && 0){ }");
+Function("L:if((function x ()3)() + arguments++) {return; } else if (new gc()) while(((x2.prop = functional)) && 0){ }");
-Function("var x = x -= '' ");
+Function("var x = x -= '' ");
-Function("switch((Math.pow ? x = 1.2e3 : 3)) { default: return; }")
+Function("switch((Math.pow ? x = 1.2e3 : 3)) { default: return; }")
Function("x = 0.1, x\ntrue\n~this");
Function("with((function (x)x2)() ^ this){return; }");
- \ No newline at end of file
+
diff --git a/test/script/basic/JDK-8019814.js b/test/script/basic/JDK-8019814.js
index 24abf53b..d3a658a4 100644
--- a/test/script/basic/JDK-8019814.js
+++ b/test/script/basic/JDK-8019814.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,7 +34,7 @@ Function("switch([]) { case 7: }");
// java.lang.AssertionError: expecting integer type or object for jump, but found double
Function("with(\nnull == (this % {}))( /x/g );");
-// java.lang.AssertionError: expecting equivalent types on stack but got double and int
+// java.lang.AssertionError: expecting equivalent types on stack but got double and int
try {
eval('Function("/*infloop*/while(((function ()4.)([z1,,], [,,]) - true++))switch(1e+81.x) { default: break; \u0009 }")');
} catch (e) {
@@ -48,11 +48,11 @@ Function("var x = x -= '' ");
Function("return (null != [,,] <= this);");
// java.lang.AssertionError: Only return value on stack allowed at return point
-// - depth=2 stack = jdk.nashorn.internal.codegen.Label$Stack@4bd0d62f
+// - depth=2 stack = jdk.nashorn.internal.codegen.Label$Stack@4bd0d62f
Function("x = 0.1, x\ntrue\n~this");
// java.lang.AssertionError: node NaN ~ window class jdk.nashorn.internal.ir.BinaryNode
-// has no symbol! [object] function _L1()
+// has no symbol! [object] function _L1()
Function("throw NaN\n~window;");
// java.lang.AssertionError: array element type doesn't match array type
@@ -65,9 +65,9 @@ try {
}
// java.lang.AssertionError: stacks jdk.nashorn.internal.codegen.Label$Stack@4918f90f
-// is not equivalent with jdk.nashorn.internal.codegen.Label$Stack@5f9b21a1 at join point
+// is not equivalent with jdk.nashorn.internal.codegen.Label$Stack@5f9b21a1 at join point
Function("if((null ^ [1]) !== (this.yoyo(false))) {var NaN, x;x\n~[,,z1] }");
// java.lang.AssertionError
-// at jdk.nashorn.internal.codegen.Attr.enterFunctionBody(Attr.java:276)
-Function("return (void ({ set each (x2)y }));");
+// at jdk.nashorn.internal.codegen.Attr.enterFunctionBody(Attr.java:276)
+Function("return (void ({ set each (x2)y }));");
diff --git a/test/script/basic/JDK-8019817.js b/test/script/basic/JDK-8019817.js
index 6611e9b4..37af9708 100644
--- a/test/script/basic/JDK-8019817.js
+++ b/test/script/basic/JDK-8019817.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
var y = 17.17;
-Function("return y % function(q) { return q; }();");
+Function("return y % function(q) { return q; }();");
function f() {
return y % function(q) { return q; }();
diff --git a/test/script/basic/JDK-8019819.js b/test/script/basic/JDK-8019819.js
index 1760ac3d..f8998508 100644
--- a/test/script/basic/JDK-8019819.js
+++ b/test/script/basic/JDK-8019819.js
@@ -23,14 +23,14 @@
/**
* JDK-8019819: scope symbol didn't get a slot in certain cases
- *
+ *
* @test
* @run
*/
function f() {
try {
- } catch(e if [].g(e)) {
- with({}) {
+ } catch(e if [].g(e)) {
+ with({}) {
throw e;
}
}
@@ -38,8 +38,8 @@ function f() {
function g() {
try {
- } catch(e) {
- with({}) {
+ } catch(e) {
+ with({}) {
throw e;
}
}
diff --git a/test/script/basic/JDK-8019821.js b/test/script/basic/JDK-8019821.js
index c296ac3c..0e797486 100644
--- a/test/script/basic/JDK-8019821.js
+++ b/test/script/basic/JDK-8019821.js
@@ -1,37 +1,37 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8019821: boolean switch value accidentally triggered "allInts" case
+ * JDK-8019821: boolean switch value accidentally triggered "allInts" case
* as boolean is considered narrower than int. This caused a ClassCastException
*
* @test
* @run
*/
-function f() {
- switch(gc()) {
- case true:
- case 1:
+function f() {
+ switch(gc()) {
+ case true:
+ case 1:
}
}
diff --git a/test/script/basic/JDK-8019822.js b/test/script/basic/JDK-8019822.js
index 2a491500..6c6fc346 100644
--- a/test/script/basic/JDK-8019822.js
+++ b/test/script/basic/JDK-8019822.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019947.js b/test/script/basic/JDK-8019947.js
index 4b64a818..52a7339a 100644
--- a/test/script/basic/JDK-8019947.js
+++ b/test/script/basic/JDK-8019947.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019963.js b/test/script/basic/JDK-8019963.js
index 5767a414..1ca749a7 100644
--- a/test/script/basic/JDK-8019963.js
+++ b/test/script/basic/JDK-8019963.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8019983.js b/test/script/basic/JDK-8019983.js
index 7851ab01..39cf813c 100644
--- a/test/script/basic/JDK-8019983.js
+++ b/test/script/basic/JDK-8019983.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,18 +24,18 @@
/**
* JDK-8019983.js return without expression combined with return with expression should produce object
* return type (undefined)
- *
+ *
* @test
* @run
*/
-function g() {
- switch(1) {
- case 0:
- case '':
+function g() {
+ switch(1) {
+ case 0:
+ case '':
default:
- return;
+ return;
}
return 10;
}
diff --git a/test/script/basic/JDK-8019985.js b/test/script/basic/JDK-8019985.js
index adc7fbf6..a4783f45 100644
--- a/test/script/basic/JDK-8019985.js
+++ b/test/script/basic/JDK-8019985.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020124.js b/test/script/basic/JDK-8020124.js
index f7735fc0..6326643a 100644
--- a/test/script/basic/JDK-8020124.js
+++ b/test/script/basic/JDK-8020124.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020132.js b/test/script/basic/JDK-8020132.js
index 49fc1b16..9cb6a767 100644
--- a/test/script/basic/JDK-8020132.js
+++ b/test/script/basic/JDK-8020132.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020223.js b/test/script/basic/JDK-8020223.js
index 9bbbad28..9d5f68a3 100644
--- a/test/script/basic/JDK-8020223.js
+++ b/test/script/basic/JDK-8020223.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020324.js b/test/script/basic/JDK-8020324.js
index 8f48f76c..0ef73256 100644
--- a/test/script/basic/JDK-8020324.js
+++ b/test/script/basic/JDK-8020324.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020325.js b/test/script/basic/JDK-8020325.js
index 5c8e64f5..c991c348 100644
--- a/test/script/basic/JDK-8020325.js
+++ b/test/script/basic/JDK-8020325.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020354.js b/test/script/basic/JDK-8020354.js
index fbfa826c..fd9b29ba 100644
--- a/test/script/basic/JDK-8020354.js
+++ b/test/script/basic/JDK-8020354.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020355.js b/test/script/basic/JDK-8020355.js
index 262c458a..e55328c2 100644
--- a/test/script/basic/JDK-8020355.js
+++ b/test/script/basic/JDK-8020355.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020356.js b/test/script/basic/JDK-8020356.js
index 062a5412..cb564ca4 100644
--- a/test/script/basic/JDK-8020356.js
+++ b/test/script/basic/JDK-8020356.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020357.js b/test/script/basic/JDK-8020357.js
index 69406371..c3bce256 100644
--- a/test/script/basic/JDK-8020357.js
+++ b/test/script/basic/JDK-8020357.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -35,7 +35,7 @@ var limit = Math.pow(2, UNSIGNED_INT_BITS)/BYTES_PER_INT_32
// A value over the limit should throw a RangeError.
try {
- Int32Array(limit)
+ new Int32Array(limit)
} catch(e) {
print(e)
}
diff --git a/test/script/basic/JDK-8020358.js b/test/script/basic/JDK-8020358.js
index 401531de..6151a951 100644
--- a/test/script/basic/JDK-8020358.js
+++ b/test/script/basic/JDK-8020358.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020380.js b/test/script/basic/JDK-8020380.js
index 90357fa7..3c71d69c 100644
--- a/test/script/basic/JDK-8020380.js
+++ b/test/script/basic/JDK-8020380.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020437.js b/test/script/basic/JDK-8020437.js
index d758355c..1a53aaf8 100644
--- a/test/script/basic/JDK-8020437.js
+++ b/test/script/basic/JDK-8020437.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020463.js b/test/script/basic/JDK-8020463.js
index 1b3830bf..6554a625 100644
--- a/test/script/basic/JDK-8020463.js
+++ b/test/script/basic/JDK-8020463.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8020508.js b/test/script/basic/JDK-8020508.js
index 304870af..3499e174 100644
--- a/test/script/basic/JDK-8020508.js
+++ b/test/script/basic/JDK-8020508.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8020508: Enforce reflection check on
+ * JDK-8020508: Enforce reflection check on
* Object.bindProperties(target, source) for beans
*
* @test
diff --git a/test/script/basic/JDK-8021122.js b/test/script/basic/JDK-8021122.js
index 769164f5..bf716fbd 100644
--- a/test/script/basic/JDK-8021122.js
+++ b/test/script/basic/JDK-8021122.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8022598.js b/test/script/basic/JDK-8022598.js
index 95f2ab49..b33bed9d 100644
--- a/test/script/basic/JDK-8022598.js
+++ b/test/script/basic/JDK-8022598.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8022731.js b/test/script/basic/JDK-8022731.js
index 635bd2d8..e44ff126 100644
--- a/test/script/basic/JDK-8022731.js
+++ b/test/script/basic/JDK-8022731.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8022903.js b/test/script/basic/JDK-8022903.js
index 1733c51a..8ab6cd41 100644
--- a/test/script/basic/JDK-8022903.js
+++ b/test/script/basic/JDK-8022903.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -43,7 +43,7 @@ for each(var color in colors) {
var capitals = new java.util.LinkedHashMap()
capitals.Sweden = "Stockholm"
-capitals.Hungary = "Budapet"
+capitals.Hungary = "Budapest"
capitals.Croatia = "Zagreb"
for(var key in capitals) {
diff --git a/test/script/basic/JDK-8022903.js.EXPECTED b/test/script/basic/JDK-8022903.js.EXPECTED
index 8d64baeb..bf13978b 100644
--- a/test/script/basic/JDK-8022903.js.EXPECTED
+++ b/test/script/basic/JDK-8022903.js.EXPECTED
@@ -5,8 +5,8 @@ red
purple
pink
capital of Sweden is Stockholm
-capital of Hungary is Budapet
+capital of Hungary is Budapest
capital of Croatia is Zagreb
Stockholm
-Budapet
+Budapest
Zagreb
diff --git a/test/script/basic/JDK-8023026.js b/test/script/basic/JDK-8023026.js
index 0a6f0272..2070de55 100644
--- a/test/script/basic/JDK-8023026.js
+++ b/test/script/basic/JDK-8023026.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8023373.js b/test/script/basic/JDK-8023373.js
index 1a019820..b8bf4188 100644
--- a/test/script/basic/JDK-8023373.js
+++ b/test/script/basic/JDK-8023373.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -50,7 +50,7 @@ var cw = new FilterWriterAdapter(sw) {
write: function(s, off, len) {
s = capitalize(s)
// Must handle overloads by arity
- if(off === undefined) {
+ if(off === undefined) {
cw.super$write(s, 0, s.length())
} else if (typeof s === "string") {
cw.super$write(s, off, len)
diff --git a/test/script/basic/JDK-8023531.js b/test/script/basic/JDK-8023531.js
index 819e46b7..9520f74e 100644
--- a/test/script/basic/JDK-8023531.js
+++ b/test/script/basic/JDK-8023531.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8023551.js b/test/script/basic/JDK-8023551.js
index 8545fbb5..f02107d2 100644
--- a/test/script/basic/JDK-8023551.js
+++ b/test/script/basic/JDK-8023551.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8023630.js b/test/script/basic/JDK-8023630.js
index f0f4c581..68cbcc22 100644
--- a/test/script/basic/JDK-8023630.js
+++ b/test/script/basic/JDK-8023630.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -50,7 +50,7 @@ var cw = new FilterWriterAdapter(sw) {
write: function(s, off, len) {
s = capitalize(s)
// Must handle overloads by arity
- if(off === undefined) {
+ if(off === undefined) {
cw_super.write(s, 0, s.length())
} else if (typeof s === "string") {
cw_super.write(s, off, len)
diff --git a/test/script/basic/JDK-8023650.js b/test/script/basic/JDK-8023650.js
index 8b01f496..d0e6178c 100644
--- a/test/script/basic/JDK-8023650.js
+++ b/test/script/basic/JDK-8023650.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8023780.js b/test/script/basic/JDK-8023780.js
index 675f22c7..0c2f5bb1 100644
--- a/test/script/basic/JDK-8023780.js
+++ b/test/script/basic/JDK-8023780.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8023784.js b/test/script/basic/JDK-8023784.js
index c8a5099d..c5b3a46a 100644
--- a/test/script/basic/JDK-8023784.js
+++ b/test/script/basic/JDK-8023784.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024120.js b/test/script/basic/JDK-8024120.js
index d2913d52..1b72cb99 100644
--- a/test/script/basic/JDK-8024120.js
+++ b/test/script/basic/JDK-8024120.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024174.js b/test/script/basic/JDK-8024174.js
index bd9206a6..c718bcd8 100644
--- a/test/script/basic/JDK-8024174.js
+++ b/test/script/basic/JDK-8024174.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024255.js b/test/script/basic/JDK-8024255.js
index 54022a5c..07933fc5 100644
--- a/test/script/basic/JDK-8024255.js
+++ b/test/script/basic/JDK-8024255.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -39,9 +39,9 @@ function check(obj, name) {
}
}
-var obj = {
+var obj = {
default: 344,
- in: 'hello',
+ in: 'hello',
if: false,
class: 4.223
}
diff --git a/test/script/basic/JDK-8024512.js b/test/script/basic/JDK-8024512.js
index c03ba212..f70477bf 100644
--- a/test/script/basic/JDK-8024512.js
+++ b/test/script/basic/JDK-8024512.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024619.js b/test/script/basic/JDK-8024619.js
index 064e0d7b..57a0895e 100644
--- a/test/script/basic/JDK-8024619.js
+++ b/test/script/basic/JDK-8024619.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024846.js b/test/script/basic/JDK-8024846.js
index ccdf8fcc..b87c8d92 100644
--- a/test/script/basic/JDK-8024846.js
+++ b/test/script/basic/JDK-8024846.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8024847.js b/test/script/basic/JDK-8024847.js
index 2ead01fd..96fdaa71 100644
--- a/test/script/basic/JDK-8024847.js
+++ b/test/script/basic/JDK-8024847.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -79,7 +79,7 @@ jlist = null;
var __array__ = [ "nashorn", "js" ];
var obj = new JSObject() {
-
+
hasMember: function(name) {
return name in __array__;
},
diff --git a/test/script/basic/JDK-8024972.js b/test/script/basic/JDK-8024972.js
index 2e940812..9e1c1b75 100644
--- a/test/script/basic/JDK-8024972.js
+++ b/test/script/basic/JDK-8024972.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025048-2.js b/test/script/basic/JDK-8025048-2.js
index c11816ba..2ee77094 100644
--- a/test/script/basic/JDK-8025048-2.js
+++ b/test/script/basic/JDK-8025048-2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
function func(x) {
- switch(x) {
+ switch(x) {
case 8: break; case false:
}
}
diff --git a/test/script/basic/JDK-8025048.js b/test/script/basic/JDK-8025048.js
index 75838a98..397ee659 100644
--- a/test/script/basic/JDK-8025048.js
+++ b/test/script/basic/JDK-8025048.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
function func(x) {
- switch(x) {
+ switch(x) {
case 8: break; case true:
}
}
diff --git a/test/script/basic/JDK-8025080.js b/test/script/basic/JDK-8025080.js
index 1ea46efa..72a695aa 100644
--- a/test/script/basic/JDK-8025080.js
+++ b/test/script/basic/JDK-8025080.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025090.js b/test/script/basic/JDK-8025090.js
index 8e42099c..5a4136f2 100644
--- a/test/script/basic/JDK-8025090.js
+++ b/test/script/basic/JDK-8025090.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025111.js b/test/script/basic/JDK-8025111.js
index 953f27c0..9e13355d 100644
--- a/test/script/basic/JDK-8025111.js
+++ b/test/script/basic/JDK-8025111.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025147.js b/test/script/basic/JDK-8025147.js
index 905a1c9c..7c239b37 100644
--- a/test/script/basic/JDK-8025147.js
+++ b/test/script/basic/JDK-8025147.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025149.js b/test/script/basic/JDK-8025149.js
index b1d33a1a..4dd880d3 100644
--- a/test/script/basic/JDK-8025149.js
+++ b/test/script/basic/JDK-8025149.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025163.js b/test/script/basic/JDK-8025163.js
index 1eaa98e8..9017d62c 100644
--- a/test/script/basic/JDK-8025163.js
+++ b/test/script/basic/JDK-8025163.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025197.js b/test/script/basic/JDK-8025197.js
index 5099b673..44b5425f 100644
--- a/test/script/basic/JDK-8025197.js
+++ b/test/script/basic/JDK-8025197.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025213.js b/test/script/basic/JDK-8025213.js
index 062a389e..5d219848 100644
--- a/test/script/basic/JDK-8025213.js
+++ b/test/script/basic/JDK-8025213.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025312.js b/test/script/basic/JDK-8025312.js
index 6f2b42f3..5256aef0 100644
--- a/test/script/basic/JDK-8025312.js
+++ b/test/script/basic/JDK-8025312.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025325.js b/test/script/basic/JDK-8025325.js
index 63dfef9d..e61929f1 100644
--- a/test/script/basic/JDK-8025325.js
+++ b/test/script/basic/JDK-8025325.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025434.js b/test/script/basic/JDK-8025434.js
index 1d429594..5c33f37f 100644
--- a/test/script/basic/JDK-8025434.js
+++ b/test/script/basic/JDK-8025434.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025486.js b/test/script/basic/JDK-8025486.js
index 8012f723..f1012a97 100644
--- a/test/script/basic/JDK-8025486.js
+++ b/test/script/basic/JDK-8025486.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025488.js b/test/script/basic/JDK-8025488.js
index 8229b9fa..2d1dfeb0 100644
--- a/test/script/basic/JDK-8025488.js
+++ b/test/script/basic/JDK-8025488.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -39,5 +39,5 @@ MyError.prototype.toString = function() {
return this.arr.toString();
}
-var e = new MyError();
+var e = new MyError();
print(e.stack.replace(/\\/g, '/'));
diff --git a/test/script/basic/JDK-8025515.js b/test/script/basic/JDK-8025515.js
index 29574d2a..b88897b6 100644
--- a/test/script/basic/JDK-8025515.js
+++ b/test/script/basic/JDK-8025515.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -47,7 +47,7 @@ function testMethodName(f, expected) {
var stack = e.nashornException.getStackTrace();
var name = getFirstScriptFrame(stack).methodName;
if (name !== expected) {
- fail("got " + stack[0].methodName + ", expected " + expected);
+ fail("got " + name + ", expected " + expected);
}
}
}
@@ -61,7 +61,7 @@ testMethodName(function() { throw new Error() }, "L:59");
var f = (function() {
return function() { a.b.c; };
})();
-testMethodName(f, "L:61$L:62");
+testMethodName(f, "f$L:62");
testMethodName((function() {
return function() { return a.b.c; };
diff --git a/test/script/basic/JDK-8025520.js b/test/script/basic/JDK-8025520.js
index 773a30ab..0e8ff802 100644
--- a/test/script/basic/JDK-8025520.js
+++ b/test/script/basic/JDK-8025520.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8025589.js b/test/script/basic/JDK-8025589.js
index a74261c1..75fdadb7 100644
--- a/test/script/basic/JDK-8025589.js
+++ b/test/script/basic/JDK-8025589.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026008.js b/test/script/basic/JDK-8026008.js
index 20c1d5f0..0064646c 100644
--- a/test/script/basic/JDK-8026008.js
+++ b/test/script/basic/JDK-8026008.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026016.js b/test/script/basic/JDK-8026016.js
index 43f268d8..4858b2c1 100644
--- a/test/script/basic/JDK-8026016.js
+++ b/test/script/basic/JDK-8026016.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026033.js b/test/script/basic/JDK-8026033.js
index 4a5d8594..550f3c26 100644
--- a/test/script/basic/JDK-8026033.js
+++ b/test/script/basic/JDK-8026033.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026042.js b/test/script/basic/JDK-8026042.js
index a853626f..860488ed 100644
--- a/test/script/basic/JDK-8026042.js
+++ b/test/script/basic/JDK-8026042.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026048.js b/test/script/basic/JDK-8026048.js
index 33789fea..9c861470 100644
--- a/test/script/basic/JDK-8026048.js
+++ b/test/script/basic/JDK-8026048.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026112.js b/test/script/basic/JDK-8026112.js
index 0e869f70..ae6f6ca3 100644
--- a/test/script/basic/JDK-8026112.js
+++ b/test/script/basic/JDK-8026112.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026125.js b/test/script/basic/JDK-8026125.js
index bb3a43d8..d67b7653 100644
--- a/test/script/basic/JDK-8026125.js
+++ b/test/script/basic/JDK-8026125.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026137.js b/test/script/basic/JDK-8026137.js
index 4a19643f..841e4f0b 100644
--- a/test/script/basic/JDK-8026137.js
+++ b/test/script/basic/JDK-8026137.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8026137: Binary evaluation order in JavaScript is load load
+ * JDK-8026137: Binary evaluation order in JavaScript is load load
* convert convert, not load convert load convert.
*
* @test
@@ -30,14 +30,16 @@
*/
try {
- (function f() { Object.defineProperty({},"x",{get: function(){return {valueOf:function(){throw 0}}}}).x - Object.defineProperty({},"x",{get: function(){throw 1}}).x })()
-}
+ (function f() {
+ Object.defineProperty({},"x",{get: function(){return {valueOf:function(){throw 0}}}}).x -
+ Object.defineProperty({},"x",{get: function(){throw 1}}).x })()
+}
catch (e) {
print(e);
}
try {
- ({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1)
+ ({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1)
} catch (e) {
print(e);
}
diff --git a/test/script/basic/JDK-8026161.js b/test/script/basic/JDK-8026161.js
index e3e88486..caef2bb5 100644
--- a/test/script/basic/JDK-8026161.js
+++ b/test/script/basic/JDK-8026161.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026162.js b/test/script/basic/JDK-8026162.js
index ccd6ee71..3f44b985 100644
--- a/test/script/basic/JDK-8026162.js
+++ b/test/script/basic/JDK-8026162.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026167.js b/test/script/basic/JDK-8026167.js
index 4959e62a..7293c4c4 100644
--- a/test/script/basic/JDK-8026167.js
+++ b/test/script/basic/JDK-8026167.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,7 +37,7 @@ e.eval('function f(e) { eval("e") } f()');
e.eval('function f() { var e = 33; eval("e") } f()');
function f() {
- Function.call.call(function x() { eval("x") }); eval("x")
+ Function.call.call(function x() { eval("x") }); eval("x")
}
try {
diff --git a/test/script/basic/JDK-8026248.js b/test/script/basic/JDK-8026248.js
index e54d3383..452b8632 100644
--- a/test/script/basic/JDK-8026248.js
+++ b/test/script/basic/JDK-8026248.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
load('nashorn:mozilla_compat.js')
-importClass(java.io.File, java.io.InputStream)
+importClass(java.io.File, java.io.InputStream)
print(File)
print(InputStream)
diff --git a/test/script/basic/JDK-8026264.js b/test/script/basic/JDK-8026264.js
index b4de01d2..4d8efedb 100644
--- a/test/script/basic/JDK-8026264.js
+++ b/test/script/basic/JDK-8026264.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026292.js b/test/script/basic/JDK-8026292.js
index 740895f2..ff338275 100644
--- a/test/script/basic/JDK-8026292.js
+++ b/test/script/basic/JDK-8026292.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026302.js b/test/script/basic/JDK-8026302.js
index 786cc118..8545c3ca 100644
--- a/test/script/basic/JDK-8026302.js
+++ b/test/script/basic/JDK-8026302.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -45,4 +45,4 @@ for (var prop in obj) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
print(desc.get);
print(desc.set);
-}
+}
diff --git a/test/script/basic/JDK-8026317.js b/test/script/basic/JDK-8026317.js
index 57bea9cb..91b5ccf2 100644
--- a/test/script/basic/JDK-8026317.js
+++ b/test/script/basic/JDK-8026317.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026367.js b/test/script/basic/JDK-8026367.js
index c5e12358..0b14ecfe 100644
--- a/test/script/basic/JDK-8026367.js
+++ b/test/script/basic/JDK-8026367.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026692.js b/test/script/basic/JDK-8026692.js
index f9f0f38c..09f11595 100644
--- a/test/script/basic/JDK-8026692.js
+++ b/test/script/basic/JDK-8026692.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026693.js b/test/script/basic/JDK-8026693.js
index fd1dd5fa..59c10eb7 100644
--- a/test/script/basic/JDK-8026693.js
+++ b/test/script/basic/JDK-8026693.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026701.js b/test/script/basic/JDK-8026701.js
index 90a1739c..35d63a44 100644
--- a/test/script/basic/JDK-8026701.js
+++ b/test/script/basic/JDK-8026701.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026805.js b/test/script/basic/JDK-8026805.js
index 0133a0b6..943c3688 100644
--- a/test/script/basic/JDK-8026805.js
+++ b/test/script/basic/JDK-8026805.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026858.js b/test/script/basic/JDK-8026858.js
index 92562ac1..912b480c 100644
--- a/test/script/basic/JDK-8026858.js
+++ b/test/script/basic/JDK-8026858.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8026955.js b/test/script/basic/JDK-8026955.js
index a54e3d96..09270f3c 100644
--- a/test/script/basic/JDK-8026955.js
+++ b/test/script/basic/JDK-8026955.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027016.js b/test/script/basic/JDK-8027016.js
index f84050fb..69fd5d70 100644
--- a/test/script/basic/JDK-8027016.js
+++ b/test/script/basic/JDK-8027016.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027024.js b/test/script/basic/JDK-8027024.js
index 890c6917..f23c8024 100644
--- a/test/script/basic/JDK-8027024.js
+++ b/test/script/basic/JDK-8027024.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8027024: String.prototype.charAt and charCodeAt do not evaluate 'self' and 'pos' arguments in right order
+ * JDK-8027024: String.prototype.charAt and charCodeAt do not evaluate 'self' and 'pos' arguments in right order
*
* @test
* @run
diff --git a/test/script/basic/JDK-8027042.js b/test/script/basic/JDK-8027042.js
index eea6373b..5977899c 100644
--- a/test/script/basic/JDK-8027042.js
+++ b/test/script/basic/JDK-8027042.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,33 +26,35 @@
*
* @test
* @run
+ * @fork
*/
// var with getter side effect
-Object.defineProperty(this, "a", { get: function() {print("get a"); return 1; }});
+Object.defineProperty(this, "a1", { get: function() {print("get a"); return 1; }});
// var with both getter and conversion side effect
-Object.defineProperty(this, "b", { get: function() {print("get b"); return {valueOf: function() { print("conv b"); return 10; }}; }});
+Object.defineProperty(this, "b1", { get: function() {print("get b"); return {valueOf: function() { print("conv b"); return 10; }}; }});
(function() {
// var with toPrimitive conversion side effect
- var c = {valueOf: function() { print("conv c"); return 100; }};
-
- print(b + (c + a));
- print(b + (c + b));
- print(b + (a + b));
- print(b + (b + c));
- print(b + (b + c));
- print(b + (c + (a - b)));
- print(b + (c + (c - b)));
- print(b + (c + (b - c)));
- print(b + (b + (a ? 2 : 3)));
- print(b + (b + (b ? 2 : 3)));
- print(b + (b + (c ? 2 : 3)));
- print(b + ((-c) + (-a)));
- print(b + ((-c) + (-b)));
- print(b + ((-c) + (-c)));
- try { print(b + new a); } catch (e) {}
- try { print(b + new b); } catch (e) {}
- try { print(b + new c); } catch (e) {}
+ var c1 = {valueOf: function() { print("conv c"); return 100; }};
+ print("start");
+ print(b1 + (c1 + a1));
+ print("done with first");
+ print(b1 + (c1 + b1));
+ print(b1 + (a1 + b1));
+ print(b1 + (b1 + c1));
+ print(b1 + (b1 + c1));
+ print(b1 + (c1 + (a1 - b1)));
+ print(b1 + (c1 + (c1 - b1)));
+ print(b1 + (c1 + (b1 - c1)));
+ print(b1 + (b1 + (a1 ? 2 : 3)));
+ print(b1 + (b1 + (b1 ? 2 : 3)));
+ print(b1 + (b1 + (c1 ? 2 : 3)));
+ print(b1 + ((-c1) + (-a1)));
+ print(b1 + ((-c1) + (-b1)));
+ print(b1 + ((-c1) + (-c1)));
+ try { print(b1 + new a1); } catch (e) {}
+ try { print(b1 + new b1); } catch (e) {}
+ try { print(b1 + new c1); } catch (e) {}
})();
diff --git a/test/script/basic/JDK-8027042.js.EXPECTED b/test/script/basic/JDK-8027042.js.EXPECTED
index 25b34e61..e05a507f 100644
--- a/test/script/basic/JDK-8027042.js.EXPECTED
+++ b/test/script/basic/JDK-8027042.js.EXPECTED
@@ -1,8 +1,10 @@
+start
get b
get a
conv c
conv b
111
+done with first
get b
get b
conv c
diff --git a/test/script/basic/JDK-8027236.js b/test/script/basic/JDK-8027236.js
index 02f9e8d8..48b53673 100644
--- a/test/script/basic/JDK-8027236.js
+++ b/test/script/basic/JDK-8027236.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027562.js b/test/script/basic/JDK-8027562.js
index 950584b4..16675dff 100644
--- a/test/script/basic/JDK-8027562.js
+++ b/test/script/basic/JDK-8027562.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027700.js b/test/script/basic/JDK-8027700.js
index 4c5445d8..1d2f4e73 100644
--- a/test/script/basic/JDK-8027700.js
+++ b/test/script/basic/JDK-8027700.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -43,7 +43,7 @@ try {
}
}
-Object.defineProperty(this, "foo", { value:0 })
+Object.defineProperty(this, "foo", { value:0 })
try {
eval("function foo() {}");
fail("should have thrown TypeError");
diff --git a/test/script/basic/JDK-8027753.js b/test/script/basic/JDK-8027753.js
index 2af0baad..4cb01878 100644
--- a/test/script/basic/JDK-8027753.js
+++ b/test/script/basic/JDK-8027753.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027828.js b/test/script/basic/JDK-8027828.js
index ab60938b..3503dd15 100644
--- a/test/script/basic/JDK-8027828.js
+++ b/test/script/basic/JDK-8027828.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8027933.js b/test/script/basic/JDK-8027933.js
index 506abc23..e723bc3d 100644
--- a/test/script/basic/JDK-8027933.js
+++ b/test/script/basic/JDK-8027933.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8028020.js b/test/script/basic/JDK-8028020.js
index 4dfa0cad..36e5a791 100644
--- a/test/script/basic/JDK-8028020.js
+++ b/test/script/basic/JDK-8028020.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8028210.js b/test/script/basic/JDK-8028210.js
index 54f113a0..f3aef0b3 100644
--- a/test/script/basic/JDK-8028210.js
+++ b/test/script/basic/JDK-8028210.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8028434.js b/test/script/basic/JDK-8028434.js
index c3374151..798ce6e7 100644
--- a/test/script/basic/JDK-8028434.js
+++ b/test/script/basic/JDK-8028434.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,28 +31,28 @@
try {
while (test.apa < 0) {
- print("x");
+ print("x");
}
} catch (e) {
var st = e.getStackTrace();
if (st.length != 1) {
- print("erroneous stacktrace length " + s.length);
+ print("erroneous stacktrace length " + s.length);
}
if (st[0].lineNumber !== 33) {
- print("erroneous stacktrace element, lineNumber=" + st[0].lineNumber + " elem=" + st);
+ print("erroneous stacktrace element, lineNumber=" + st[0].lineNumber + " elem=" + st);
}
}
try {
do {
- print("x");
+ print("x");
} while (test.apa < 0);
} catch (e) {
var st = e.getStackTrace();
if (st.length != 1) {
- print("erroneous stacktrace length " + s.length);
+ print("erroneous stacktrace length " + s.length);
}
if (st[0].lineNumber !== 49) {
- print("erroneous stacktrace element, lineNumber= " + st[0].lineNumber + " elem=" + st);
+ print("erroneous stacktrace element, lineNumber= " + st[0].lineNumber + " elem=" + st);
}
}
diff --git a/test/script/basic/JDK-8029364.js b/test/script/basic/JDK-8029364.js
index dfa8ea9d..fe935626 100644
--- a/test/script/basic/JDK-8029364.js
+++ b/test/script/basic/JDK-8029364.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/runsunspider-eager.js b/test/script/basic/JDK-8029384.js
index db358d28..00124009 100644
--- a/test/script/basic/runsunspider-eager.js
+++ b/test/script/basic/JDK-8029384.js
@@ -1,33 +1,33 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8029384: Function expression self-symbol not available for eval
*
* @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
*/
-load(__DIR__ + "runsunspider.js");
-
+var g = function f() { print(eval("f.x")) }
+g.x = "tada!"
+g()
diff --git a/test/script/basic/JDK-8029384.js.EXPECTED b/test/script/basic/JDK-8029384.js.EXPECTED
new file mode 100644
index 00000000..c8f91232
--- /dev/null
+++ b/test/script/basic/JDK-8029384.js.EXPECTED
@@ -0,0 +1 @@
+tada!
diff --git a/test/script/basic/JDK-8029467.js b/test/script/basic/JDK-8029467.js
index ad7f2fde..76b280a7 100644
--- a/test/script/basic/JDK-8029467.js
+++ b/test/script/basic/JDK-8029467.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,3 +32,4 @@ print((function (x) { return x ? true : 0 })(true))
print((function (x) { if(x) { return true } else { return 0 } })(true))
print(typeof (function (x) { return x ? 1 : "123" })(true) === "number")
print(typeof (function (x) { if(x) { return 1 } else { return "123" } })(true) === "number")
+
diff --git a/test/script/basic/JDK-8029667.js b/test/script/basic/JDK-8029667.js
index c0c2d156..016b4e8b 100644
--- a/test/script/basic/JDK-8029667.js
+++ b/test/script/basic/JDK-8029667.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
function f(x) {
- return (function inner() {
+ return (function inner() {
var y; (function dummy() { return y })() // force own scope for the inner function
with({}) { // 'with' block turns off fast scopes
return x
@@ -39,8 +39,8 @@ function f(x) {
print(f(1));
print(f(2));
-function g(x) {
- (function inner() {
+function g(x) {
+ (function inner() {
var y; (function dummy() { return y })() // force own scope for the inner function
with({}) { // 'with' block turns off fast scopes
// Test setter as well as getter
@@ -83,9 +83,7 @@ for(var i in withScopes) {
}
}
main();
-}
+}
print(withScopes[0].func);
print(withScopes[1].func);
-
-
diff --git a/test/script/basic/JDK-8030182.js b/test/script/basic/JDK-8030182.js
index f3c492d4..f9f0e9b0 100644
--- a/test/script/basic/JDK-8030182.js
+++ b/test/script/basic/JDK-8030182.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8030182_2.js b/test/script/basic/JDK-8030182_2.js
index de507e1d..4c2f5c42 100644
--- a/test/script/basic/JDK-8030182_2.js
+++ b/test/script/basic/JDK-8030182_2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,13 +28,13 @@
* @run
*/
-var str = "";
+var str = "";
// large code to force splitting
-for (i = 0; i < 1000; ++i)
+for (i = 0; i < 1000; ++i)
str +="o = new Object()\n";
-str +="g()";
+str +="g()";
// check that "$split" or some such internal method
// does not appear in script stack trace!!
diff --git a/test/script/basic/JDK-8030182_2.js.EXPECTED b/test/script/basic/JDK-8030182_2.js.EXPECTED
index 772e504d..afc582e9 100644
--- a/test/script/basic/JDK-8030182_2.js.EXPECTED
+++ b/test/script/basic/JDK-8030182_2.js.EXPECTED
@@ -1,3 +1,3 @@
ReferenceError: "g" is not defined
- at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@0:-1)
+ at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>:-1)
at <program> (test/script/basic/JDK-8030182_2.js:42)
diff --git a/test/script/basic/JDK-8030197.js b/test/script/basic/JDK-8030197.js
index 366d33df..5b4ee0b9 100644
--- a/test/script/basic/JDK-8030197.js
+++ b/test/script/basic/JDK-8030197.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8030199.js b/test/script/basic/JDK-8030199.js
index b6d32fb1..c4759aec 100644
--- a/test/script/basic/JDK-8030199.js
+++ b/test/script/basic/JDK-8030199.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8030200.js b/test/script/basic/JDK-8030200.js
index e49eec7d..a62fa498 100644
--- a/test/script/basic/JDK-8030200.js
+++ b/test/script/basic/JDK-8030200.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8030202.js b/test/script/basic/JDK-8030202.js
index 6cf56475..e2b014d9 100644
--- a/test/script/basic/JDK-8030202.js
+++ b/test/script/basic/JDK-8030202.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8030809.js b/test/script/basic/JDK-8030809.js
index 01c7687c..99b21c3e 100644
--- a/test/script/basic/JDK-8030809.js
+++ b/test/script/basic/JDK-8030809.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
function func() {
- (function() {
+ (function() {
throw new Error();
})();
}
diff --git a/test/script/basic/JDK-8031317.js b/test/script/basic/JDK-8031317.js
index 240a6337..6cf43fe9 100644
--- a/test/script/basic/JDK-8031317.js
+++ b/test/script/basic/JDK-8031317.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8031359.js b/test/script/basic/JDK-8031359.js
index 278fd7d2..c2d4ac60 100644
--- a/test/script/basic/JDK-8031359.js
+++ b/test/script/basic/JDK-8031359.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8031983.js b/test/script/basic/JDK-8031983.js
index f0bfca13..7f3631de 100644
--- a/test/script/basic/JDK-8031983.js
+++ b/test/script/basic/JDK-8031983.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8031983: Error objects should capture stack at the constructor
+ * JDK-8031983: Error objects should capture stack at the constructor
*
* @test
* @run
diff --git a/test/script/basic/JDK-8032004.js b/test/script/basic/JDK-8032004.js
index 2995566c..29e8cb0c 100644
--- a/test/script/basic/JDK-8032004.js
+++ b/test/script/basic/JDK-8032004.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8032004: instance property "message" of Error objects should be non-enumerable
+ * JDK-8032004: instance property "message" of Error objects should be non-enumerable
*
* @test
* @run
diff --git a/test/script/basic/JDK-8032068.js b/test/script/basic/JDK-8032068.js
index 570789d7..f98f0c66 100644
--- a/test/script/basic/JDK-8032068.js
+++ b/test/script/basic/JDK-8032068.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8034055.js b/test/script/basic/JDK-8034055.js
index 0a21d9f9..ff870680 100644
--- a/test/script/basic/JDK-8034055.js
+++ b/test/script/basic/JDK-8034055.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8035312.js b/test/script/basic/JDK-8035312.js
new file mode 100644
index 00000000..b027f2ec
--- /dev/null
+++ b/test/script/basic/JDK-8035312.js
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8035312 push to frozen array must not increase length property
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+function printArrayDataClass(x) {
+ if (typeof Debug !== 'undefined') {
+ print(Debug.getArrayDataClass(x));
+ }
+}
+
+function gpush(x, elem) {
+ try {
+ print("Pushing " + elem + " to " + x);
+ x.push(elem);
+ } catch (e) {
+ print("caught error" + e);
+ }
+ print("\tarray is now [" + x + "] length is = " + x.length);
+ print();
+ printArrayDataClass(x);
+}
+
+function gpop(x) {
+ try {
+ print("Popping from " + x);
+ x.pop();
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ print("e of wrong type " + e);
+ }
+ }
+ print("\tarray is now [" + x + "] length is = " + x.length);
+ print();
+ printArrayDataClass(x);
+}
+
+function checkArray(x) {
+ print();
+ print(">>> Push test");
+
+ var olen = x.length;
+ gpush(x, 0);
+
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x[3] === " + x[3] + " (should be 0)");
+ print("x[4] === " + x[4] + " (should be undefined)");
+
+ print();
+ print(">>> Pop test");
+ gpop(x);
+ gpop(x);
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x === " + x);
+
+ for (var i = 0 ; i < 5; i++) {
+ gpop(x);
+ }
+
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x === " + x);
+}
+
+print("*** Freezing");
+var frozen = [1,2,3];
+Object.freeze(frozen);
+checkArray(frozen);
+printArrayDataClass(frozen);
+
+//so far so good
+
+print();
+print("*** Other length not writable issues");
+var lengthNotWritable = [1,2,3];
+Object.defineProperty(lengthNotWritable, "length", { writable: false });
+checkArray(lengthNotWritable);
+printArrayDataClass(lengthNotWritable);
+
+function set(array, from, to, stride) {
+ //add three elements
+ for (var i = from; i < to; i+=stride) {
+ try {
+ print("Writing " + i);
+ array[i] = i;
+ printArrayDataClass(array);
+ } catch (e) {
+ print(e instanceof TypeError);
+ }
+ }
+}
+
+//define empty array with non writable length
+var arr = [1];
+Object.defineProperty(arr, "length", { writable: false });
+
+var olen2 = arr.length;
+
+set(arr, 0, 3, 1);
+
+if (arr.length != olen2) {
+ throw new ("error: " + arr.length + " != " + olen2);
+}
+
+print();
+print("array writing 0-3, with 1 stride, array = " + arr);
+print("length = " + arr.length + ", but elements are: " + arr[0] + " " + arr[1] + " " + arr[2]);
+print();
+
+//do the same but sparse/deleted range
+var arr2 = [1];
+Object.defineProperty(arr2, "length", { writable: false });
+
+print("initial length = " + arr2.length);
+var olen3 = arr2.length;
+
+set(arr2, 0, 30, 3);
+
+if (arr2.length != olen3) {
+ throw new ("error: " + arr2.length + " != " + olen3);
+}
+
+print();
+var larger = 20;
+print("array writing 0-" + larger + ", with 3 stride, array = " + arr2);
+print("length = " + arr2.length + ", but elements are: " + arr2[0] + " " + arr2[1] + " " + arr2[2]);
+
+for (var i = 0; i < larger; i++) {
+ if (arr2[i] === undefined) {
+ continue;
+ }
+ print(arr2[i] + " has length " + arr2.length);
+}
+
+print();
+var elem = 0x7fffffff - 10;
+printArrayDataClass(arr2);
+print("adding a new element high up in the array");
+print("length before element was added " + arr2.length);
+print("putting sparse at " + elem);
+arr2[elem] = "sparse";
+print("length after element was added " + arr2.length + " should be the same");
+printArrayDataClass(arr2);
+
+print();
+print("Printing arr2 - this will fail if length is > 28 and it is " + arr2.length);
+print("arr2 = [" + arr2 + "]");
+print("new length that should not be writable = " + arr2.length);
+print(arr2[elem] === "sparse");
+print(arr2[elem]);
+for (var i = 0; i < larger; i++) {
+ print(arr2[i]);
+}
+for (var key in arr2) {
+ print(key + ":" + arr2[key]);
+}
+
+//issues reported by sundar - generic setter doesn't go through push/pop bulkable
+
+function sundarExample2(arr, _writable) {
+ print("Checking if push works for bulkable non bulkable arrays - Setting length property not allowed");
+ arr[0] = "bar";
+ print(arr.length + " should be 1"); // should be 1
+ print(arr[0] + " should be bar");
+ print("["+ arr + "] should be [bar]");
+
+ // Object.defineProperty(arr, "length", { configurable: _writable });
+ Object.defineProperty(arr, "length", { writable: _writable });
+ arr[1] = "baz";
+
+ if (_writable) {
+ print(arr.length + " should be 2");
+ print(arr[0] + " should be bar");
+ print(arr[1] + " should be baz");
+ print("["+ arr + "] should be [bar,baz]");
+ } else {
+ print(arr.length + " should STILL be 1");
+ print(arr[0] + " should be bar");
+ print(arr[1] + " should be baz");
+ print("["+ arr + "] should be [bar]");
+ }
+}
+
+var newArr1 = [];
+sundarExample2(newArr1, false);
+print();
+try {
+ sundarExample2(newArr1, true);
+ print("should not get here");
+} catch (e) {
+ if (!(e instanceof TypeError)) {
+ print("Wrong exception");
+ }
+ print("got TypeError when redefining length, as expected")
+}
+print();
+
+sundarExample2([], true);
+print("Done");
diff --git a/test/script/basic/JDK-8035312.js.EXPECTED b/test/script/basic/JDK-8035312.js.EXPECTED
new file mode 100644
index 00000000..07d576f1
--- /dev/null
+++ b/test/script/basic/JDK-8035312.js.EXPECTED
@@ -0,0 +1,186 @@
+*** Freezing
+
+>>> Push test
+Pushing 0 to 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x[3] === undefined (should be 0)
+x[4] === undefined (should be undefined)
+
+>>> Pop test
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+
+*** Other length not writable issues
+
+>>> Push test
+Pushing 0 to 1,2,3
+caught errorTypeError: "length" is not a writable property of [object Array]
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x[3] === 0 (should be 0)
+x[4] === undefined (should be undefined)
+
+>>> Pop test
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 0
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 1
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 2
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+array writing 0-3, with 1 stride, array = 0
+length = 1, but elements are: 0 undefined 2
+
+initial length = 1
+Writing 0
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 3
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 6
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 9
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 12
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 15
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 18
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 21
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 24
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 27
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+array writing 0-20, with 3 stride, array = 0
+length = 1, but elements are: 0 undefined undefined
+0 has length 1
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+adding a new element high up in the array
+length before element was added 1
+putting sparse at 2147483637
+length after element was added 1 should be the same
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+Printing arr2 - this will fail if length is > 28 and it is 1
+arr2 = [0]
+new length that should not be writable = 1
+true
+sparse
+0
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+0:0
+2147483637:sparse
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+1 should STILL be 1
+bar should be bar
+baz should be baz
+[bar] should be [bar]
+
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+got TypeError when redefining length, as expected
+
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+2 should be 2
+bar should be bar
+baz should be baz
+[bar,baz] should be [bar,baz]
+Done
diff --git a/test/script/basic/JDK-8035312_2.js b/test/script/basic/JDK-8035312_2.js
new file mode 100644
index 00000000..a7da0b0d
--- /dev/null
+++ b/test/script/basic/JDK-8035312_2.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8035312_2 - length setter and iterators
+ *
+ * @test
+ * @run
+ */
+
+"use strict"
+
+function printArray(a,n) {
+ print("PRINT_ARRAY CALLED: length = " + a.length);
+ print();
+
+ print("INDEXED");
+ for (var x = 0; x<n; x++) {
+ print("\t" + x + ":"+a[x]);
+ }
+ print("KEYS");
+ for (var key in a) {
+ print("\t" + key + ";" + a[key]);
+ }
+}
+
+var b = [1,2,3];
+
+Object.defineProperty(b, "length", { writable: false });
+var high = 8;
+b[high] = high;
+
+printArray(b, high + 5);
+
+var c = [1,2,3];
+c[high] = high;
+print();
+print("element[" + high + "]: " + c.length + " " + c[high]);
+print("Resetting length");
+c.length = 3;
+print("element[" + high + "]: " + c.length + " " + c[high]);
+print();
+
+printArray(c, high + 5);
+print();
diff --git a/test/script/basic/JDK-8035312_2.js.EXPECTED b/test/script/basic/JDK-8035312_2.js.EXPECTED
new file mode 100644
index 00000000..7ea96b39
--- /dev/null
+++ b/test/script/basic/JDK-8035312_2.js.EXPECTED
@@ -0,0 +1,47 @@
+PRINT_ARRAY CALLED: length = 3
+
+INDEXED
+ 0:1
+ 1:2
+ 2:3
+ 3:undefined
+ 4:undefined
+ 5:undefined
+ 6:undefined
+ 7:undefined
+ 8:8
+ 9:undefined
+ 10:undefined
+ 11:undefined
+ 12:undefined
+KEYS
+ 0;1
+ 1;2
+ 2;3
+ 8;8
+
+element[8]: 9 8
+Resetting length
+element[8]: 3 undefined
+
+PRINT_ARRAY CALLED: length = 3
+
+INDEXED
+ 0:1
+ 1:2
+ 2:3
+ 3:undefined
+ 4:undefined
+ 5:undefined
+ 6:undefined
+ 7:undefined
+ 8:undefined
+ 9:undefined
+ 10:undefined
+ 11:undefined
+ 12:undefined
+KEYS
+ 0;1
+ 1;2
+ 2;3
+
diff --git a/test/script/basic/JDK-8035312_3.js b/test/script/basic/JDK-8035312_3.js
new file mode 100644
index 00000000..bcb6c6f2
--- /dev/null
+++ b/test/script/basic/JDK-8035312_3.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8035312_3 - sparse array, non writable length
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+
+Object.defineProperty(b, "length", { writable: false });
+var high = 23534343;
+b[high-10] = high-10;
+
+print(b[high-10]);
+
+var c = [1,2,3];
+c[high-10] = high-10;
+c.length = 3;
+print(c);
+print(c[high-10]);
diff --git a/test/script/basic/JDK-8035312_3.js.EXPECTED b/test/script/basic/JDK-8035312_3.js.EXPECTED
new file mode 100644
index 00000000..9592ff96
--- /dev/null
+++ b/test/script/basic/JDK-8035312_3.js.EXPECTED
@@ -0,0 +1,3 @@
+23534333
+1,2,3
+undefined
diff --git a/test/script/basic/JDK-8035312_4.js b/test/script/basic/JDK-8035312_4.js
new file mode 100644
index 00000000..13dbf444
--- /dev/null
+++ b/test/script/basic/JDK-8035312_4.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8035312_4 - pushes and pops for non writable length
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+Object.defineProperty(b, "length", { writable: false });
+
+try {
+ b.push(4);
+} catch (e) {
+ print("length = " + b.length);
+ print("i caught an error");
+}
+print(b);
+print(b[3]);
+print("length = " + b.length);
+
+var c = [1,2,3];
+Object.defineProperty(c, "length", { writable: false });
+
+for (var i = 0; i < 5; i++) {
+ try {
+ c.pop();
+ } catch (e) {
+ print("length = " + c.length);
+ print("I caught an error");
+ print(c);
+ }
+}
+
+print(c);
+print(c[3]);
+print("length = " + b.length);
diff --git a/test/script/basic/JDK-8035312_4.js.EXPECTED b/test/script/basic/JDK-8035312_4.js.EXPECTED
new file mode 100644
index 00000000..2495603f
--- /dev/null
+++ b/test/script/basic/JDK-8035312_4.js.EXPECTED
@@ -0,0 +1,23 @@
+length = 3
+i caught an error
+1,2,3
+4
+length = 3
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+1,2,
+undefined
+length = 3
diff --git a/test/script/basic/JDK-8035312_5.js b/test/script/basic/JDK-8035312_5.js
new file mode 100644
index 00000000..83edd16e
--- /dev/null
+++ b/test/script/basic/JDK-8035312_5.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8035312_5 - pushes and pops for frozen array
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+Object.freeze(b);
+
+try {
+ b.push(4);
+} catch (e) {
+ print("length = " + b.length);
+ print("i caught an error");
+}
+print(b);
+print(b[3]);
+print("length = " + b.length);
+
+var c = [1,2,3];
+Object.freeze(c);
+
+for (var i = 0; i < 5; i++) {
+ try {
+ c.pop();
+ } catch (e) {
+ print("length = " + c.length);
+ print("I caught an error");
+ print(c);
+ }
+}
+
+print(c);
+print(c[3]);
+print("length = " + b.length);
+
diff --git a/test/script/basic/JDK-8035312_5.js.EXPECTED b/test/script/basic/JDK-8035312_5.js.EXPECTED
new file mode 100644
index 00000000..6fb4bba1
--- /dev/null
+++ b/test/script/basic/JDK-8035312_5.js.EXPECTED
@@ -0,0 +1,6 @@
+1,2,3
+undefined
+length = 3
+1,2,3
+undefined
+length = 3
diff --git a/test/script/basic/JDK-8037562.js b/test/script/basic/JDK-8037562.js
index 7534a0da..bcd828cf 100644
--- a/test/script/basic/JDK-8037562.js
+++ b/test/script/basic/JDK-8037562.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8038413.js b/test/script/basic/JDK-8038413.js
new file mode 100644
index 00000000..d7b5ed21
--- /dev/null
+++ b/test/script/basic/JDK-8038413.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8038413: NPE in unboxInteger
+ *
+ * @test
+ * @run
+ */
+
+// When adapting a method returning Integer to an optimistic call site
+// expecting int, can't forego filters because of null. That is, the
+// Integer->int conversion can't be left to the automatisms present in
+// java.lang.invoke.MethodHandle.asType() because of potential null
+// values.
+var IntegerArray = Java.type("java.lang.Integer[]");
+var arr = new IntegerArray(1);
+print(arr[0]);
diff --git a/test/script/basic/JDK-8038413.js.EXPECTED b/test/script/basic/JDK-8038413.js.EXPECTED
new file mode 100644
index 00000000..19765bd5
--- /dev/null
+++ b/test/script/basic/JDK-8038413.js.EXPECTED
@@ -0,0 +1 @@
+null
diff --git a/test/script/basic/JDK-8038945.js b/test/script/basic/JDK-8038945.js
new file mode 100644
index 00000000..efaccd60
--- /dev/null
+++ b/test/script/basic/JDK-8038945.js
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8038945.js : test various undefined strict intrinsics and that they
+ * aren't erroneously applied when undefined is in any scope but global
+ *
+ * @test
+ * @run
+ */
+
+//:program internals={print=0, f1=0, f2=0, f3=0, f4=0, undefined=0, f5=0} externals=null
+
+//f1 internals={} externals={undefined=0}
+function f1(x) {
+ return x === undefined;
+}
+
+//f2 internals={} externals=null
+function f2(x, undefined) {
+ return x === undefined;
+}
+
+//f3 internals={x=0} externals=null
+function f3(x) {
+ //f3$f3_2 internals={} externals={x=0}
+ function f3_2(undefined) {
+ return x === undefined;
+ }
+ return f3_2(17);
+}
+
+//f4 internals={x=0} externals=null
+function f4(x) {
+ //f4$f4_2 internals={} externals={x=0}
+ function f4_2() {
+ var undefined = 17;
+ return x === undefined;
+ }
+ return f4_2();
+}
+
+//f5 internals={x=0, undefined=0} externals=null
+function f5(x) {
+ var undefined = 17;
+ //f5$f5_2 internals={} externals={x=0, undefined=0}
+ function f5_2() {
+ return x === undefined;
+ }
+ return f5_2();
+}
+
+print(" 1: " + f1(17) + " === false");
+print(" 2: " + f2(17) + " === false");
+print(" 3: " + f3(17) + " === true");
+print(" 4: " + f4(17) + " === true");
+print(" 5: " + f5(17) + " === true");
+
+//recompile
+print(" 6: " + f1("17") + " === false");
+print(" 7: " + f2("17") + " === false");
+print(" 8: " + f3("17") + " === false");
+print(" 9: " + f4("17") + " === false");
+print("10: " + f5("17") + " === false");
+
+//g1 internals={} externals={undefined=0}
+function g1(x) {
+ return x !== undefined;
+}
+
+//g2 internals={} externals=null
+function g2(x, undefined) {
+ return x !== undefined;
+}
+
+//g3 internals={x=0} externals=null
+function g3(x) {
+ //g3$g3_2 internals={} externals={x=0}
+ function g3_2(undefined) {
+ return x !== undefined;
+ }
+ return g3_2(17);
+}
+
+//g4 internals={x=0} externals=null
+function g4(x) {
+ //f4$f4_2 internals={} externals={x=0}
+ function g4_2() {
+ var undefined = 17;
+ return x !== undefined;
+ }
+ return g4_2();
+}
+
+//g5 internals={x=0, undefined=0} externals=null
+function g5(x) {
+ var undefined = 17;
+ //g5$g5_2 internals={} externals={x=0, undefined=0}
+ function g5_2() {
+ return x !== undefined;
+ }
+ return g5_2();
+}
+
+print("11: " + g1(17) + " === true");
+print("12: " + g2(17) + " === true");
+print("13: " + g3(17) + " === false");
+print("14: " + g4(17) + " === false");
+print("15: " + g5(17) + " === false");
+
+//recompile
+print("16: " + g1("17") + " === true");
+print("17: " + g2("17") + " === true");
+print("18: " + g3("17") + " === true");
+print("19: " + g4("17") + " === true");
+print("20: " + g5("17") + " === true");
+
+//h1 internals={} externals={undefined=0}
+function h1(x) {
+ return undefined === x;
+}
+
+//h2 internals={} externals=null
+function h2(x, undefined) {
+ return undefined === x;
+}
+
+//h3 internals={x=0} externals=null
+function h3(x) {
+ //h3$f3_2 internals={} externals={x=0}
+ function h3_2(undefined) {
+ return undefined === x;
+ }
+ return h3_2(17);
+}
+
+//h4 internals={x=0} externals=null
+function h4(x) {
+ //h4$h4_2 internals={} externals={x=0}
+ function h4_2() {
+ var undefined = 17;
+ return undefined === x;
+ }
+ return h4_2();
+}
+
+//h5 internals={x=0, undefined=0} externals=null
+function h5(x) {
+ var undefined = 17;
+ //h5$h5_2 internals={} externals={x=0, undefined=0}
+ function h5_2() {
+ return undefined === x;
+ }
+ return h5_2();
+}
+
+print("21: " + h1(17) + " === false");
+print("22: " + h2(17) + " === false");
+print("23: " + h3(17) + " === true");
+print("24: " + h4(17) + " === true");
+print("25: " + h5(17) + " === true");
+
+//recompile
+print("26: " + h1("17") + " === false");
+print("27: " + h2("17") + " === false");
+print("28: " + h3("17") + " === false");
+print("29: " + h4("17") + " === false");
+print("30: " + h5("17") + " === false");
+
+//i1 internals={} externals={undefined=0}
+function i1(x) {
+ return undefined !== x;
+}
+
+//i2 internals={} externals=null
+function i2(x, undefined) {
+ return undefined !== x;
+}
+
+//i3 internals={x=0} externals=null
+function i3(x) {
+ //i3$f3_2 internals={} externals={x=0}
+ function i3_2(undefined) {
+ return undefined !== x;
+ }
+ return i3_2(17);
+}
+
+//i4 internals={x=0} externals=null
+function i4(x) {
+ //i4$i4_2 internals={} externals={x=0}
+ function i4_2() {
+ var undefined = 17;
+ return undefined !== x;
+ }
+ return i4_2();
+}
+
+//h5 internals={x=0, undefined=0} externals=null
+function i5(x) {
+ var undefined = 17;
+ //i5$i5_2 internals={} externals={x=0, undefined=0}
+ function i5_2() {
+ return undefined !== x;
+ }
+ return i5_2();
+}
+
+print("31: " + i1(17) + " === true");
+print("32: " + i2(17) + " === true");
+print("33: " + i3(17) + " === false");
+print("34: " + i4(17) + " === false");
+print("35: " + i5(17) + " === false");
+
+//recompile
+print("36: " + i1("17") + " === true");
+print("37: " + i2("17") + " === true");
+print("38: " + i3("17") + " === true");
+print("39: " + i4("17") + " === true");
+print("40: " + i5("17") + " === true");
diff --git a/test/script/basic/JDK-8038945.js.EXPECTED b/test/script/basic/JDK-8038945.js.EXPECTED
new file mode 100644
index 00000000..4d8dbc39
--- /dev/null
+++ b/test/script/basic/JDK-8038945.js.EXPECTED
@@ -0,0 +1,40 @@
+ 1: false === false
+ 2: false === false
+ 3: true === true
+ 4: true === true
+ 5: true === true
+ 6: false === false
+ 7: false === false
+ 8: false === false
+ 9: false === false
+10: false === false
+11: true === true
+12: true === true
+13: false === false
+14: false === false
+15: false === false
+16: true === true
+17: true === true
+18: true === true
+19: true === true
+20: true === true
+21: false === false
+22: false === false
+23: true === true
+24: true === true
+25: true === true
+26: false === false
+27: false === false
+28: false === false
+29: false === false
+30: false === false
+31: true === true
+32: true === true
+33: false === false
+34: false === false
+35: false === false
+36: true === true
+37: true === true
+38: true === true
+39: true === true
+40: true === true
diff --git a/test/script/basic/JDK-8039387.js b/test/script/basic/JDK-8039387.js
index 8f903c1a..562b29af 100644
--- a/test/script/basic/JDK-8039387.js
+++ b/test/script/basic/JDK-8039387.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8040024.js b/test/script/basic/JDK-8040024.js
new file mode 100644
index 00000000..86ce6838
--- /dev/null
+++ b/test/script/basic/JDK-8040024.js
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8040024: NaN comparisons were failing
+ *
+ * @test
+ * @run
+ */
+
+function f(x) {
+ if((x - '0') <= 9) {
+ print("FAIL if <=");
+ } else {
+ print("OK");
+ }
+
+ if((x - '0') < 9) {
+ print("FAIL if <");
+ } else {
+ print("OK");
+ }
+
+ if((x - '0') >= 9) {
+ print("FAIL if >=");
+ } else {
+ print("OK");
+ }
+
+ if((x - '0') > 9) {
+ print("FAIL if >");
+ } else {
+ print("OK");
+ }
+
+ while((x - '0') <= 9) {
+ print("FAIL while <=");
+ break;
+ }
+
+ while((x - '0') < 9) {
+ print("FAIL while <");
+ break;
+ }
+
+ while((x - '0') > 9) {
+ print("FAIL while >");
+ break;
+ }
+
+ while((x - '0') >= 9) {
+ print("FAIL while >=");
+ break;
+ }
+
+ var i = 0;
+ do {
+ print("do-while <= only once");
+ if(++i == 2) { break; }
+ } while((x - '0') <= 9);
+
+ var i = 0;
+ do {
+ print("do-while < only once");
+ if(++i == 2) { break; }
+ } while((x - '0') < 9);
+
+ var i = 0;
+ do {
+ print("do-while >= only once");
+ if(++i == 2) { break; }
+ } while((x - '0') >= 9);
+
+ var i = 0;
+ do {
+ print("do-while > only once");
+ if(++i == 2) { break; }
+ } while((x - '0') > 9);
+}
+f('%')
diff --git a/test/script/basic/JDK-8040024.js.EXPECTED b/test/script/basic/JDK-8040024.js.EXPECTED
new file mode 100644
index 00000000..96233020
--- /dev/null
+++ b/test/script/basic/JDK-8040024.js.EXPECTED
@@ -0,0 +1,8 @@
+OK
+OK
+OK
+OK
+do-while <= only once
+do-while < only once
+do-while >= only once
+do-while > only once
diff --git a/test/script/basic/JDK-8041995.js b/test/script/basic/JDK-8041995.js
new file mode 100644
index 00000000..9da26b72
--- /dev/null
+++ b/test/script/basic/JDK-8041995.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8041995: optimistic object property maps were only updated if the outermost program
+ * point in a property setter failed, not an inner one, which is wrong.
+ *
+ * @test
+ * @run
+ */
+
+function xyzzy() {
+ return 17.4711;
+}
+var obj = {
+ z: -xyzzy()
+};
+print(obj.z);
+
+function phlug() {
+ var obj = {
+ 4: -Infinity,
+ 5: Infinity,
+ length: 5 - Math.pow(2, 32)
+ };
+
+ return Array.prototype.lastIndexOf.call(obj, -Infinity) === 4;
+}
+
+var d = new Date;
+print(phlug());
+var d2 = new Date - d;
+print(d2 < 5000); // if this takes more than five seconds we have read the double length as an int
+
+function wrong() {
+ var obj = {
+ length1: 5 - Math.pow(2, 32),
+ length2: 4 - Math.pow(2, 32),
+ length3: 3 - Math.pow(2, 32),
+ length4: 2 - Math.pow(2, 32),
+ length5: 1 - Math.pow(2, 32),
+ length6: Math.pow(2, 32)
+ };
+ for (var i in obj) {
+ print(obj[i]);
+ }
+}
+
+wrong();
diff --git a/test/script/basic/JDK-8041995.js.EXPECTED b/test/script/basic/JDK-8041995.js.EXPECTED
new file mode 100644
index 00000000..accabf46
--- /dev/null
+++ b/test/script/basic/JDK-8041995.js.EXPECTED
@@ -0,0 +1,9 @@
+-17.4711
+true
+true
+-4294967291
+-4294967292
+-4294967293
+-4294967294
+-4294967295
+4294967296
diff --git a/test/script/basic/JDK-8041998.js b/test/script/basic/JDK-8041998.js
index 33e4d136..c19f8a28 100644
--- a/test/script/basic/JDK-8041998.js
+++ b/test/script/basic/JDK-8041998.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8042364.js b/test/script/basic/JDK-8042364.js
index d8b81e24..97f36cf8 100644
--- a/test/script/basic/JDK-8042364.js
+++ b/test/script/basic/JDK-8042364.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* JDK-8042364: Make __proto__ ES6 draft compliant
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/JDK-8043133.js b/test/script/basic/JDK-8043133.js
new file mode 100644
index 00000000..b1f9e375
--- /dev/null
+++ b/test/script/basic/JDK-8043133.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8043133: Fix corner cases of JDK-8041995
+ *
+ * @test
+ * @run
+ */
+
+var x = {}
+var b = false;
+// Ternary expression is not optimistic, yet the analyzer must still
+// find the optimistic subexpression f() that triggered deoptimizing
+// recompilation.
+Object.defineProperty(x, 'foo', { value: b ? b : f() });
+print(x.foo); // Must print "Hello world" instead of 0
+
+function f() {
+ return "Hello World!"
+}
diff --git a/test/script/basic/JDK-8043133.js.EXPECTED b/test/script/basic/JDK-8043133.js.EXPECTED
new file mode 100644
index 00000000..980a0d5f
--- /dev/null
+++ b/test/script/basic/JDK-8043133.js.EXPECTED
@@ -0,0 +1 @@
+Hello World!
diff --git a/test/script/basic/JDK-8043232.js b/test/script/basic/JDK-8043232.js
new file mode 100644
index 00000000..fa46b415
--- /dev/null
+++ b/test/script/basic/JDK-8043232.js
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8043232: Index selection of overloaded java new constructors
+ *
+ * @test
+ * @run
+ */
+
+// call explicit constructor
+print(new (java.awt["Color(int,int,int)"])(255,0,255));
+// print the constructor itself
+print(java.awt["Color(int,int,int)"]);
+
+// store constructor to call later
+var Color = java.awt["Color(int,int,int)"];
+// call stored constructor
+print(new Color(33, 233, 2))
+
+// check if default constructor works
+var obj = new (java.lang["Object()"])();
+if (obj.class != java.lang.Object.class) {
+ fail("obj is a java.lang.Object");
+}
+
+// expected failure cases.
+function checkIt(func) {
+ try {
+ func();
+ throw new Error("should have thrown TypeError");
+ } catch(e) {
+ if (! (e instanceof TypeError)) {
+ fail("Expected TypeError, got " + e);
+ }
+ print(e);
+ }
+}
+
+// constructor of a non-existent class
+checkIt(function() new (java.lang["NonExistent(String)"])());
+
+// non-existent constructor of an existing class
+checkIt(function() new (java.lang["Object(String)"])());
+
+// garbage signature string
+checkIt(function() new (java.lang["Object()xxxxx"])());
+checkIt(function() new (java.lang["Object("])());
+checkIt(function() new (java.lang["Object)"])());
+
+var System = Java.type("java.lang.System");
+// try to do 'new' on static method
+checkIt(function() new (System.getProperty)("java.version"));
+
+// try to do 'new' on an instance method
+var println = System.out.println;
+checkIt(function() new println("hello"));
+
+// call constructor as normal method (without 'new')
+checkIt(function() Color());
+
+// try constructor on interface
+checkIt(function() new java.lang["Runnable()"]);
+checkIt(function() new java.lang["Runnable(int)"]);
+
+// try constructor on abstrace class
+try {
+ new java.io["InputStream()"];
+ throw new Error("should have thrown exception!");
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/JDK-8043232.js.EXPECTED b/test/script/basic/JDK-8043232.js.EXPECTED
new file mode 100644
index 00000000..03382ea5
--- /dev/null
+++ b/test/script/basic/JDK-8043232.js.EXPECTED
@@ -0,0 +1,14 @@
+java.awt.Color[r=255,g=0,b=255]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
+java.awt.Color[r=33,g=233,b=2]
+TypeError: No such Java class: java.lang.NonExistent
+TypeError: No such Java constructor: Object(String)
+TypeError: Java constructor signature invalid: Object()xxxxx
+TypeError: Java constructor signature invalid: Object(
+TypeError: Java constructor signature invalid: Object)
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new".
+TypeError: No such Java constructor: Runnable()
+TypeError: No such Java constructor: Runnable(int)
+java.lang.InstantiationException: java.io.InputStream
diff --git a/test/script/basic/JDK-8043235.js b/test/script/basic/JDK-8043235.js
new file mode 100644
index 00000000..05de8f33
--- /dev/null
+++ b/test/script/basic/JDK-8043235.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8043235: Type-based optimizations interfere with continuation methods
+ *
+ * @test
+ * @run
+ */
+
+function g() {
+ return "Hello World!"
+}
+
+function f1() {
+ var c;
+ var paused = false;
+ // If we didn't disable nullCheck specialization for expressions
+ // containing a deoptimization site, we'd get an AssertionError
+ while (!paused && (null !== (c = g()))) {
+ print(c);
+ paused = true;
+ }
+}
+
+function f2() {
+ var c;
+ var paused = false;
+ // If we didn't disable undefinedCheck specialization for expressions
+ // containing a deoptimization site, we'd get an AssertionError
+ while (!paused && (undefined !== (c = g()))) {
+ print(c);
+ paused = true;
+ }
+}
+
+f1();
+f2();
diff --git a/test/script/basic/JDK-8043235.js.EXPECTED b/test/script/basic/JDK-8043235.js.EXPECTED
new file mode 100644
index 00000000..f28b3913
--- /dev/null
+++ b/test/script/basic/JDK-8043235.js.EXPECTED
@@ -0,0 +1,2 @@
+Hello World!
+Hello World!
diff --git a/test/script/basic/JDK-8043431.js b/test/script/basic/JDK-8043431.js
new file mode 100644
index 00000000..270db1c5
--- /dev/null
+++ b/test/script/basic/JDK-8043431.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8043431: Fix yet another corner case of JDK-8041995
+ *
+ * @test
+ * @run
+ */
+
+var a = "Hello World!";
+
+// Without the fix, evaluating "a" optimistically will start a
+// deoptimizing recompilation in a nested object literal, and trigger an
+// assertion in code generator.
+var x = {
+ foo: {
+ value: a
+ }
+};
+
+print(x.foo.value);
diff --git a/test/script/basic/JDK-8043431.js.EXPECTED b/test/script/basic/JDK-8043431.js.EXPECTED
new file mode 100644
index 00000000..980a0d5f
--- /dev/null
+++ b/test/script/basic/JDK-8043431.js.EXPECTED
@@ -0,0 +1 @@
+Hello World!
diff --git a/test/script/basic/JDK-8043930.js b/test/script/basic/JDK-8043930.js
index a89b3541..a7c93f42 100644
--- a/test/script/basic/JDK-8043930.js
+++ b/test/script/basic/JDK-8043930.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * JDK-8043930: TypeError when attemping to create an instance of non-public class could be better
+ * JDK-8043930: TypeError when attemping to create an instance of non-public class could be better
*
* @test
* @run
diff --git a/test/script/basic/JDK-8044520.js b/test/script/basic/JDK-8044520.js
index edcaa116..6086ec0b 100644
--- a/test/script/basic/JDK-8044520.js
+++ b/test/script/basic/JDK-8044520.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/ranges_disabled.js b/test/script/basic/JDK-8044533.js
index 5bc8846e..b3f04078 100644
--- a/test/script/basic/ranges_disabled.js
+++ b/test/script/basic/JDK-8044533.js
@@ -1,32 +1,31 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
+ * JDK-8044533: Deoptimizing negation produces wrong result for zero
*
- * @test
- * @run
+ * @test
+ * @run
*/
-load(__DIR__ + "ranges_payload.js");
+print(1/(function() { var f = 0; return -f; })())
diff --git a/test/script/basic/JDK-8044533.js.EXPECTED b/test/script/basic/JDK-8044533.js.EXPECTED
new file mode 100644
index 00000000..879e80ee
--- /dev/null
+++ b/test/script/basic/JDK-8044533.js.EXPECTED
@@ -0,0 +1 @@
+-Infinity
diff --git a/test/script/basic/JDK-8044534.js b/test/script/basic/JDK-8044534.js
new file mode 100644
index 00000000..e274328a
--- /dev/null
+++ b/test/script/basic/JDK-8044534.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8044534: Constant folding for unary + should produce int for boolean literals
+ *
+ * @test
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect;
+
+print(inspect(+true, "+true "));
+print(inspect(+false, "+false"));
+print(inspect(-true, "-true "));
+print(inspect(-false, "-false"));
diff --git a/test/script/basic/JDK-8044534.js.EXPECTED b/test/script/basic/JDK-8044534.js.EXPECTED
new file mode 100644
index 00000000..69c8e4cf
--- /dev/null
+++ b/test/script/basic/JDK-8044534.js.EXPECTED
@@ -0,0 +1,4 @@
++true : int
++false: int
+-true : int
+-false: double
diff --git a/test/script/basic/JDK-8044612.js b/test/script/basic/JDK-8044612.js
index 6980cd1b..9994d87a 100644
--- a/test/script/basic/JDK-8044612.js
+++ b/test/script/basic/JDK-8044612.js
@@ -34,4 +34,4 @@ if ("hello".replace("h", "$") != "$ello") {
if ("hello".replace("o", "$x") != "hell$x") {
fail("String.prototype.replace failed to handle '$x' as replacement");
-}
+}
diff --git a/test/script/basic/JDK-8044695.js b/test/script/basic/JDK-8044695.js
index 2e7b7742..3f94ffb5 100644
--- a/test/script/basic/JDK-8044695.js
+++ b/test/script/basic/JDK-8044695.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8044750.js b/test/script/basic/JDK-8044750.js
index ee6fa4d5..b084d572 100644
--- a/test/script/basic/JDK-8044750.js
+++ b/test/script/basic/JDK-8044750.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/JDK-8046013.js b/test/script/basic/JDK-8046013.js
new file mode 100644
index 00000000..e3a5ac4e
--- /dev/null
+++ b/test/script/basic/JDK-8046013.js
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8046013: TypeError: Cannot apply "with" to non script object
+ *
+ * @test
+ * @run
+ */
+
+var obj = loadWithNewGlobal({
+ script: "({ f: 33 })",
+ name: "test"
+});
+
+with (obj) {
+ print("f = " + f);
+}
+
+var obj2 = loadWithNewGlobal({
+ script: "var obj = Object.create({ foo: 42 }); obj.bar = 'hello'; obj",
+ name: "test2"
+});
+
+with (obj2) {
+ print("foo = " + foo);
+ print("bar = " + bar);
+}
+
+var obj3 = loadWithNewGlobal({
+ script: "({ f: 33, func: function() { print('this.f =', this.f); } })",
+ name: "test"
+});
+
+with(obj3) {
+ func();
+}
diff --git a/test/script/basic/JDK-8046013.js.EXPECTED b/test/script/basic/JDK-8046013.js.EXPECTED
new file mode 100644
index 00000000..4b612ed6
--- /dev/null
+++ b/test/script/basic/JDK-8046013.js.EXPECTED
@@ -0,0 +1,4 @@
+f = 33
+foo = 42
+bar = hello
+this.f = 33
diff --git a/test/script/basic/JDK-8046026.js b/test/script/basic/JDK-8046026.js
new file mode 100644
index 00000000..585621fd
--- /dev/null
+++ b/test/script/basic/JDK-8046026.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8046026: CompiledFunction.relinkComposableInvoker assert is being hit
+ * JDK-8044770: crash with jdk9-dev/nashorn during global object initialization from MT test
+ * JDK-8047770: NPE in deoptimizing recompilation in multithreaded
+ *
+ * @test
+ * @run
+ */
+
+(function() {
+var n = 1 << 25;
+var ThreadLocalRandom = java.util.concurrent.ThreadLocalRandom;
+var m = java.util.stream.IntStream.range(0, n)
+ .parallel() // this is the essence of this test. We must trigger parallel execution
+ .filter(function() {
+ var tlr = ThreadLocalRandom.current();
+
+ var x = tlr.nextDouble(-1.0, 1.0);
+ var y = tlr.nextDouble(-1.0, 1.0);
+
+ return x * x + y * y <= 1.0;
+ })
+ .count();
+var pi = (4.0 * m) / n;
+print(pi.toFixed(2));
+})()
diff --git a/test/script/basic/JDK-8046026.js.EXPECTED b/test/script/basic/JDK-8046026.js.EXPECTED
new file mode 100644
index 00000000..6324d401
--- /dev/null
+++ b/test/script/basic/JDK-8046026.js.EXPECTED
@@ -0,0 +1 @@
+3.14
diff --git a/test/script/basic/JDK-8046905.js b/test/script/basic/JDK-8046905.js
new file mode 100644
index 00000000..b11a6ad2
--- /dev/null
+++ b/test/script/basic/JDK-8046905.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8046905: apply on apply is broken
+ *
+ * @test
+ * @run
+ */
+
+var apply = Function.prototype.apply;
+var call = Function.prototype.call;
+var sort = Array.prototype.sort;
+var join = Array.prototype.join;
+
+// Running three times so that we test an already linked call site too:
+// i==0: linking initially with assumed optimistic returned type int.
+// i==1: linking after deoptimization with returned type Object.
+// i==2: re-running code linked in previous iteration. This will
+// properly exercise the guards too.
+print("1 level of apply")
+for(i = 0; i < 3; ++i) {
+ print(sort.apply([4,3,2,1]))
+}
+print("2 levels of apply")
+for(i = 0; i < 3; ++i) {
+ print(apply.apply(sort,[[4,3,2,1]]))
+}
+print("3 levels of apply")
+for(i = 0; i < 3; ++i) {
+ print(apply.apply(apply,[sort,[[4,3,2,1]]]))
+}
+print("4 levels of apply")
+for(i = 0; i < 3; ++i) {
+ print(apply.apply(apply,[apply,[sort,[[4,3,2,1]]]]))
+}
+print("5 levels of apply")
+for(i = 0; i < 3; ++i) {
+ print(apply.apply(apply,[apply,[apply,[sort,[[4,3,2,1]]]]]))
+}
+print("Many levels of apply!")
+for(i = 0; i < 3; ++i) {
+ print(apply.apply(apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[sort,[[4,3,2,1]]]]]]]]]]]]]]]]]]]]]]))
+}
+
+print("different invocations that'll trigger relinking")
+var invocation = [sort,[[4,3,2,1]]];
+for(i = 0; i < 4; ++i) {
+ print(apply.apply(apply,[apply,invocation]))
+ // First change after i==1, so it relinks an otherwise stable linkage
+ if(i == 1) {
+ invocation = [sort,[[8,7,6,5]]];
+ } else if(i == 2) {
+ invocation = [join,[[8,7,6,5],["-"]]];
+ }
+}
+
+print("Many levels of call!")
+for(i = 0; i < 3; ++i) {
+ print(call.call(call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,sort,[4,3,2,1]))
+}
+
+print("call apply call apply call... a lot");
+for(i = 0; i < 3; ++i) {
+ print(apply.call(call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [sort, [4,3,2,1]]]]]]]))
+}
+
+print("apply call apply call apply... a lot");
+for(i = 0; i < 3; ++i) {
+ print(call.apply(apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, sort, [[4,3,2,1]]]]]]]]]))
+}
diff --git a/test/script/basic/JDK-8046905.js.EXPECTED b/test/script/basic/JDK-8046905.js.EXPECTED
new file mode 100644
index 00000000..0cee6789
--- /dev/null
+++ b/test/script/basic/JDK-8046905.js.EXPECTED
@@ -0,0 +1,41 @@
+1 level of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+2 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+3 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+4 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+5 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+Many levels of apply!
+1,2,3,4
+1,2,3,4
+1,2,3,4
+different invocations that'll trigger relinking
+1,2,3,4
+1,2,3,4
+5,6,7,8
+8-7-6-5
+Many levels of call!
+1,2,3,4
+1,2,3,4
+1,2,3,4
+call apply call apply call... a lot
+1,2,3,4
+1,2,3,4
+1,2,3,4
+apply call apply call apply... a lot
+1,2,3,4
+1,2,3,4
+1,2,3,4
diff --git a/test/script/basic/JDK-8047035.js b/test/script/basic/JDK-8047035.js
new file mode 100644
index 00000000..dc44921f
--- /dev/null
+++ b/test/script/basic/JDK-8047035.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047035: (function() "hello")() crashes in Lexer with jdk9
+ *
+ * @test
+ * @run
+ */
+
+// should not print ")" at the end
+print(function() "hello");
+print(function() '');
+
+// The following should not crash inside lexer
+print((function() '')());
+print((function() "hello")());
diff --git a/test/script/basic/JDK-8047035.js.EXPECTED b/test/script/basic/JDK-8047035.js.EXPECTED
new file mode 100644
index 00000000..0c4ab07b
--- /dev/null
+++ b/test/script/basic/JDK-8047035.js.EXPECTED
@@ -0,0 +1,4 @@
+function() "hello"
+function() ''
+
+hello
diff --git a/test/script/basic/JDK-8047057.js b/test/script/basic/JDK-8047057.js
new file mode 100644
index 00000000..bd38ee90
--- /dev/null
+++ b/test/script/basic/JDK-8047057.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047057: Add a regression test for the passing test cases from JDK-8042304
+ *
+ * @test
+ * @run
+ */
+
+// commented out makeFuncAndCall calls are still result in crash
+// Tests commented with //** fail only when assertions are turned on
+
+function makeFuncAndCall(code) {
+ Function(code)();
+}
+
+function makeFuncExpectError(code, ErrorType) {
+ try {
+ makeFuncAndCall(code);
+ } catch (e) {
+ if (! (e instanceof ErrorType)) {
+ fail(ErrorType.name + " expected, got " + e);
+ }
+ }
+}
+
+makeFuncAndCall("switch(0) { default: {break;} return }");
+makeFuncAndCall("L: { { break L; } return; }");
+makeFuncAndCall("L: { while(0) break L; return; }");
+makeFuncExpectError("L: {while(0) break L; return [](); }", TypeError);
+makeFuncAndCall("do with({}) break ; while(0);");
+makeFuncAndCall("while(0) with({}) continue ;");
+makeFuncAndCall("eval([]);");
+makeFuncAndCall("try{} finally{[]}");
+makeFuncAndCall("try { } catch(x if 1) { try { } catch(x2) { } }");
+makeFuncAndCall("try { } catch(x if 1) { try { return; } catch(x2) { { } } }");
+makeFuncAndCall("Error() * (false)[-0]--");
+makeFuncAndCall("try { var x = 1, x = null; } finally { }");
+makeFuncAndCall("try { var x = {}, x = []; } catch(x3) { }");
+makeFuncAndCall("[delete this]");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
+makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
+makeFuncExpectError("eval(\"x4\", x3);", ReferenceError);
+makeFuncAndCall("with({5.0000000000000000000000: String()}){(false); }");
+makeFuncAndCall("try { var x = undefined, x = 5.0000000000000000000000; } catch(x) { x = undefined; }");
+makeFuncAndCall("(function (x){ x %= this}(false))");
+makeFuncAndCall("eval.apply.apply(function(){ eval('') })");
+makeFuncAndCall("(false % !this) && 0");
+makeFuncAndCall("with({8: 'fafafa'.replace()}){ }");
+makeFuncAndCall("(function (x) '' )(true)");
+makeFuncExpectError("new eval(function(){})", TypeError);
+makeFuncAndCall('eval("23", ({})[/x/])');
diff --git a/test/script/basic/JDK-8047067.js b/test/script/basic/JDK-8047067.js
new file mode 100644
index 00000000..2d8f1404
--- /dev/null
+++ b/test/script/basic/JDK-8047067.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047067: all eval arguments need to be copied in Lower
+ *
+ * @test
+ * @run
+ */
+
+// The second expression triggers optimistic deoptimization, and if not
+// all eval arguments were copied in Lower, we'd end up with duplicate
+// program points that'd cause incorrect continuation program point in
+// the rest-of, and therefore a bad stack, and therefore an AIOOBE in
+// the continuation setup code.
+eval("23", ({})[/x/])
diff --git a/test/script/basic/JDK-8047078.js b/test/script/basic/JDK-8047078.js
new file mode 100644
index 00000000..984e4f29
--- /dev/null
+++ b/test/script/basic/JDK-8047078.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047078: ArrayLiteral mutability caused trouble in optimistic types
+ *
+ * @test
+ * @run
+ */
+
+function makeFuncAndCall(code) {
+ Function(code)();
+}
+
+makeFuncAndCall("eval([]);");
+makeFuncAndCall("eval([1]);");
+makeFuncAndCall("eval([1,2,3,,4]);");
+makeFuncAndCall("try{} finally{[]}");
diff --git a/test/script/basic/JDK-8047166.js b/test/script/basic/JDK-8047166.js
new file mode 100644
index 00000000..74e3ae58
--- /dev/null
+++ b/test/script/basic/JDK-8047166.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
+ *
+ * @test
+ * @run
+ */
+
+(function(){do with({}) break ; while(0);})();
diff --git a/test/script/basic/JDK-8047357.js b/test/script/basic/JDK-8047357.js
new file mode 100644
index 00000000..17e4d133
--- /dev/null
+++ b/test/script/basic/JDK-8047357.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047357: More precise synthetic return + unreachable throw
+ *
+ * @test
+ * @run
+ */
+
+print((function() { switch(0) { default: {var x; break ; } throw x; } })());
+print((function() { switch(0) { default: {break;} return; } })());
diff --git a/test/script/basic/JDK-8047357.js.EXPECTED b/test/script/basic/JDK-8047357.js.EXPECTED
new file mode 100644
index 00000000..d4f80bf8
--- /dev/null
+++ b/test/script/basic/JDK-8047357.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined
+undefined
diff --git a/test/script/basic/JDK-8047359.js b/test/script/basic/JDK-8047359.js
new file mode 100644
index 00000000..812f3414
--- /dev/null
+++ b/test/script/basic/JDK-8047359.js
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047359: large string size RangeError should be thrown rather than reporting negative length
+ *
+ * @test
+ * @run
+ */
+
+try {
+ var s = " "; for (var i=0;i<31;++i) s+=s; s.length;
+ throw new Error("should have thrown RangeError!");
+} catch (e) {
+ if (! (e instanceof RangeError)) {
+ fail("RangeError expected, got " + e);
+ }
+}
+
+try {
+ var s = " "; for (var i=0;i<31;++i) s+=s;
+ throw new Error("should have thrown RangeError!");
+} catch (e) {
+ if (! (e instanceof RangeError)) {
+ fail("RangeError expected, got " + e);
+ }
+}
diff --git a/test/script/basic/JDK-8047369.js b/test/script/basic/JDK-8047369.js
new file mode 100644
index 00000000..e2b09840
--- /dev/null
+++ b/test/script/basic/JDK-8047369.js
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047369: Add regression tests for passing test cases of JDK-8024971
+ *
+ * @test
+ * @run
+ * @option -scripting
+ */
+
+function makeFuncAndCall(code) {
+ Function(code)();
+}
+
+function makeFuncExpectError(code, ErrorType) {
+ try {
+ makeFuncAndCall(code);
+ } catch (e) {
+ if (! (e instanceof ErrorType)) {
+ fail(ErrorType.name + " expected, got " + e);
+ }
+ }
+}
+
+function evalExpectError(code, ErrorType) {
+ try {
+ eval(code)();
+ } catch (e) {
+ if (! (e instanceof ErrorType)) {
+ fail(ErrorType.name + " expected, got " + e);
+ }
+ }
+}
+
+function evalExpectValue(code, value) {
+ if (eval(code) != value) {
+ fail("Expected " + value + " with eval of " + code);
+ }
+}
+
+makeFuncAndCall("for(x.x in 0) {}");
+// bug JDK-8047357
+// makeFuncAndCall("switch((null >> x3)) { default: {var x; break ; }\nthrow x; }");
+makeFuncExpectError("switch(x) { case 8: break; case false: }", ReferenceError);
+makeFuncAndCall("try { return true; } finally { return false; } ");
+makeFuncAndCall("({ get 1e81(){} })");
+makeFuncAndCall("{var x, x3;try { return 0; } finally { return 3/0; } }");
+makeFuncExpectError("with(x ? 1e81 : (x2.constructor = 0.1)) {}", ReferenceError);
+makeFuncAndCall("while(x-=1) {var x=0; }");
+makeFuncAndCall("while((x-=false) && 0) { var x = this; }");
+makeFuncAndCall("/*infloop*/while(x4-=x) var x, x4 = x1;");
+makeFuncAndCall("/*infloop*/L:while(x+=null) { this;var x = /x/g ; }");
+makeFuncAndCall("while((x1|=0.1) && 0) { var x1 = -0, functional; }");
+makeFuncAndCall("with({}) return (eval(\"arguments\"));");
+
+evalExpectValue(<<CODE
+ var s = "(function() { return y })()";
+ (function() {
+ with({ y:1 })
+ eval(s)
+ })();
+ (function() {
+ with({
+ get y() { return "get"; }
+ })
+ return eval(s)
+ })();
+CODE, "get");
+
+// bug JDK-8047359
+// evalExpectValue("s = ' '; for (var i=0;i<31;++i) s+=s; s.length", RangeError);
+
+evalExpectValue(<<CODE
+ function f(o) {
+ var eval=0;
+ with({
+ get eval() { return o.eval }
+ })
+ return eval("1+2");
+ }
+ f(this);
+CODE, 3)
+
+evalExpectValue(<<CODE
+ function f() {
+ var a=1,e=2;
+ try {
+ throw 3
+ } catch(e) {
+ return + function g(){return eval('a+e')}()
+ }
+ }
+ f();
+CODE, 4);
+
+//evalExpectValue(
+// "function f(){var a=1; with({get a(){return false}}) return a}; f()", false);
+
+evalExpectError("function public() {\"use strict\"}", SyntaxError);
+evalExpectError("function f(public) {\"use strict\"}", SyntaxError);
+evalExpectError("function f() { switch(x) {} } f()", ReferenceError);
+
+// bug JDK-8047364
+// makeFuncAndCall("L1:try { return } finally { break L1 }");
+
+evalExpectValue(<<CODE
+ function f() {
+ function g() { return 0 }
+ function g() { return 1 }
+ function g$1() { return 2 }
+ return g$1()
+ }
+
+ f();
+CODE, 2);
+
+evalExpectValue(<<CODE
+ function f() {
+ function g() {return 0 }
+ var h = function g() { return 1 };
+ function g$1() { return 2 };
+ return h()
+ }
+
+ f()
+CODE, 1);
+
+evalExpectValue(<<CODE
+ function f() {
+ var obj = { get ":"() {} }
+ var desc = Object.getOwnPropertyDescriptor(obj, ":")
+ return desc.get.name
+ }
+
+ f()
+CODE, ":");
+
+evalExpectValue(<<CODE
+ function f() {
+ var obj = { set ":"(a) {} };
+ var desc = Object.getOwnPropertyDescriptor(obj, ":");
+ return desc.set;
+ }
+
+ f()
+CODE, "set \":\"(a) {}");
+
+// bug JDK-8047366
+// evalExpectValue("(1000000000000000128).toString()", "1000000000000000100");
+// evalExpectValue("(1000000000000000128).toFixed().toString()", "1000000000000000128");
+
+try {
+ Function("-", {
+ toString: function() {
+ throw "err"
+ }
+ })();
+} catch (e) {
+ if (e != "err") {
+ fail("Expected 'err' here, got " + e);
+ }
+}
+evalExpectError("function f() { switch(x) {} } f()", ReferenceError);
+Array.prototype.splice.call(Java.type("java.util.HashMap"))
+Array.prototype.slice.call(Java.type("java.util.HashMap"))
diff --git a/test/script/basic/JDK-8047371.js b/test/script/basic/JDK-8047371.js
new file mode 100644
index 00000000..d8fc4012
--- /dev/null
+++ b/test/script/basic/JDK-8047371.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047371: local variable declaration in TypeEvaluator should use ScriptObject.addOwnProperty instead of .set
+ *
+ * @test
+ * @run
+ */
+
+print((function(){ var a=1; with({ get a() { return false } }) return a })());
+
diff --git a/test/script/basic/JDK-8047371.js.EXPECTED b/test/script/basic/JDK-8047371.js.EXPECTED
new file mode 100644
index 00000000..c508d536
--- /dev/null
+++ b/test/script/basic/JDK-8047371.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/test/script/basic/JDK-8047728.js b/test/script/basic/JDK-8047728.js
new file mode 100644
index 00000000..ba7b0339
--- /dev/null
+++ b/test/script/basic/JDK-8047728.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047728: (function(x){var o={x:0}; with(o){delete x} return o.x})() evaluates to 0 instead of undefined
+ *
+ * @test
+ * @run
+ */
+
+function func(x) {
+ var o = {x:0};
+ with(o){
+ delete x;
+ }
+ return o.x
+}
+
+if (typeof func() != 'undefined') {
+ fail("expected undefined from 'func' call");
+}
+
+function func2() {
+ var x;
+ var o = {x:0};
+ with(o){
+ delete x;
+ }
+ return o.x
+}
+
+if (typeof func2() != 'undefined') {
+ fail("expected undefined from 'func2' call");
+}
diff --git a/test/script/basic/JDK-8047764-strict.js b/test/script/basic/JDK-8047764-strict.js
new file mode 100644
index 00000000..d10b5b37
--- /dev/null
+++ b/test/script/basic/JDK-8047764-strict.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047764: Indexed or polymorphic set on global affects Object.prototype
+ *
+ * @test
+ * @run
+ */
+
+// Same as JDK-8047764.js but running in strict mode
+"use strict";
+
+// Test global set operation on properties defined in Object.prototype
+
+Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
+Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
+
+try {
+ prop1 = 1;
+ print("prop 1: " + prop2);
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ prop2 = 2;
+ print("prop 2: " + prop2);
+} catch (e) {
+ print(e.name);
+}
+
+// Make sure various ways of setting global toString don't affect Object.prototype.toString
+
+function checkToString() {
+ print(global);
+ print(Object.prototype);
+ print(global.toString === Object.prototype.toString);
+ print(objProtoToString === Object.prototype.toString);
+}
+
+var global = this;
+var objProtoToString = Object.prototype.toString;
+global["toString"] = function() { return "global toString 1"; };
+checkToString();
+global.toString = function() { return "global toString 2"; };
+checkToString();
+toString = function() { return "global toString 3"; };
+checkToString();
diff --git a/test/script/basic/JDK-8047764-strict.js.EXPECTED b/test/script/basic/JDK-8047764-strict.js.EXPECTED
new file mode 100644
index 00000000..c452cfac
--- /dev/null
+++ b/test/script/basic/JDK-8047764-strict.js.EXPECTED
@@ -0,0 +1,15 @@
+setting prop1: 1
+prop 1: 1
+TypeError
+global toString 1
+[object Object]
+false
+true
+global toString 2
+[object Object]
+false
+true
+global toString 3
+[object Object]
+false
+true
diff --git a/test/script/basic/JDK-8047764.js b/test/script/basic/JDK-8047764.js
new file mode 100644
index 00000000..3920323f
--- /dev/null
+++ b/test/script/basic/JDK-8047764.js
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047764: Indexed or polymorphic set on global affects Object.prototype
+ *
+ * @test
+ * @run
+ */
+
+// Test global set operation on properties defined in Object.prototype
+
+Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
+Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
+
+try {
+ prop1 = 1;
+ print("prop 1: " + prop2);
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ prop2 = 2;
+ print("prop 2: " + prop2);
+} catch (e) {
+ print(e.name);
+}
+
+// Make sure various ways of setting global toString don't affect Object.prototype.toString
+
+function checkToString() {
+ print(global);
+ print(Object.prototype);
+ print(global.toString === Object.prototype.toString);
+ print(objProtoToString === Object.prototype.toString);
+}
+
+var global = this;
+var objProtoToString = Object.prototype.toString;
+global["toString"] = function() { return "global toString 1"; };
+checkToString();
+global.toString = function() { return "global toString 2"; };
+checkToString();
+toString = function() { return "global toString 3"; };
+checkToString();
+
+// Test setters on 'with' object
+
+var p = { prop3: 3, toString: function() { return "[object p]"; }};
+Object.defineProperty(p, "prop4", { get: function() { print("get", this); return 4; }, set: function(v) { print("set", this, v); }});
+var o = Object.create(p);
+o.toString = function() { return "[object o]"; };
+
+with(o) {
+ (function() {
+ var m = 5;
+ (function() {
+ print(prop3);
+ prop3 = m;
+ print(prop3);
+ print(prop4);
+ prop4 = m;
+ print(prop4);
+ })();
+ })();
+}
+
+print(o.hasOwnProperty("prop3"));
+print(o.prop3);
+print(p.prop3);
+print(o.hasOwnProperty("prop4"));
+print(o.prop4);
+print(p.prop4);
diff --git a/test/script/basic/JDK-8047764.js.EXPECTED b/test/script/basic/JDK-8047764.js.EXPECTED
new file mode 100644
index 00000000..5c9b0eb5
--- /dev/null
+++ b/test/script/basic/JDK-8047764.js.EXPECTED
@@ -0,0 +1,30 @@
+setting prop1: 1
+prop 1: 1
+prop 2: 1
+global toString 1
+[object Object]
+false
+true
+global toString 2
+[object Object]
+false
+true
+global toString 3
+[object Object]
+false
+true
+3
+5
+get [object o]
+4
+set [object o] 5
+get [object o]
+4
+true
+5
+3
+false
+get [object o]
+4
+get [object p]
+4
diff --git a/test/script/basic/JDK-8047959.js b/test/script/basic/JDK-8047959.js
new file mode 100644
index 00000000..179fb888
--- /dev/null
+++ b/test/script/basic/JDK-8047959.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8047959: bindings created for declarations in eval code are not mutable
+ *
+ * @test
+ * @run
+ */
+
+eval("var x=10;");
+print('delete x? ' + delete x);
+print('typeof x = ' + typeof x);
+
+eval("function f() {}");
+print('delete f? ' + delete f);
+print('typeof f = ' + typeof f);
+
+var foo = 223;
+print('delete foo? ' + delete foo);
+print('typeof foo = ' + typeof foo);
+
+function func() {}
+print('delete func? ' + delete func);
+print('typeof func = ' + typeof func);
+
+eval("var foo = 33;");
+print("delete foo? " + delete foo);
+print("typeof foo? " + typeof foo);
+print("foo = " + foo);
+
+var x = "global";
+(function(){
+ eval("var x='local'");
+ print("x in function = "+ x);
+ print("delete x? = " + delete x);
+ print("x after delete = " + x);
+})();
+print("x = " + x);
diff --git a/test/script/basic/JDK-8047959.js.EXPECTED b/test/script/basic/JDK-8047959.js.EXPECTED
new file mode 100644
index 00000000..935f1002
--- /dev/null
+++ b/test/script/basic/JDK-8047959.js.EXPECTED
@@ -0,0 +1,15 @@
+delete x? false
+typeof x = number
+delete f? true
+typeof f = undefined
+delete foo? false
+typeof foo = number
+delete func? false
+typeof func = function
+delete foo? false
+typeof foo? number
+foo = 33
+x in function = local
+delete x? = true
+x after delete = global
+x = global
diff --git a/test/script/basic/JDK-8048071.js b/test/script/basic/JDK-8048071.js
new file mode 100644
index 00000000..aec0c7c1
--- /dev/null
+++ b/test/script/basic/JDK-8048071.js
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ var x = 1;
+ with ({ eval: this.eval }) {
+ eval("var x = 23");
+ }
+
+ return x;
+}
+
+print(func());
+print("typeof x? " + typeof x);
+
+print((function(global){
+ var x = 1;
+ with(global) {
+ eval("eval('var x=0')");
+ }
+ return x;
+})(this));
+print("typeof x? " + typeof x);
+
+print((function(global){
+ var x = 1;
+ with({eval: global.eval}) {
+ eval("eval('var x=0')");
+ }
+ return x;
+})(this));
+print("typeof x? " + typeof x);
+
+// not-builtin eval cases
+
+(function () {
+ function eval(str) {
+ print("local eval called: " + str);
+ print(this);
+ }
+
+ with({}) {
+ eval("hello");
+ }
+})();
+
+(function () {
+ with({
+ eval:function(str) {
+ print("with's eval called: " + str);
+ print("this = " + this);
+ print("this.foo = " + this.foo);
+ },
+ foo: 42
+ }) {
+ eval("hello")
+ }
+})();
diff --git a/test/script/basic/JDK-8048071.js.EXPECTED b/test/script/basic/JDK-8048071.js.EXPECTED
new file mode 100644
index 00000000..5234bb1a
--- /dev/null
+++ b/test/script/basic/JDK-8048071.js.EXPECTED
@@ -0,0 +1,11 @@
+23
+typeof x? undefined
+0
+typeof x? undefined
+0
+typeof x? undefined
+local eval called: hello
+[object global]
+with's eval called: hello
+this = [object Object]
+this.foo = 42
diff --git a/test/script/basic/JDK-8048079_1a.js b/test/script/basic/JDK-8048079_1a.js
new file mode 100644
index 00000000..8d37e19e
--- /dev/null
+++ b/test/script/basic/JDK-8048079_1a.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
diff --git a/test/script/basic/JDK-8048079_1a.js.EXPECTED b/test/script/basic/JDK-8048079_1a.js.EXPECTED
new file mode 100644
index 00000000..e677550c
--- /dev/null
+++ b/test/script/basic/JDK-8048079_1a.js.EXPECTED
@@ -0,0 +1 @@
+parsed and compiled ok prototype.js
diff --git a/test/script/basic/JDK-8048079_1b.js b/test/script/basic/JDK-8048079_1b.js
new file mode 100644
index 00000000..8106e1e4
--- /dev/null
+++ b/test/script/basic/JDK-8048079_1b.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048079: Persistent code store is broken after optimistic types merge
+ *
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
diff --git a/test/script/basic/JDK-8048079_1b.js.EXPECTED b/test/script/basic/JDK-8048079_1b.js.EXPECTED
new file mode 100644
index 00000000..28dd1b9d
--- /dev/null
+++ b/test/script/basic/JDK-8048079_1b.js.EXPECTED
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/test/script/basic/JDK-8048079_2a.js b/test/script/basic/JDK-8048079_2a.js
new file mode 100644
index 00000000..7d08c004
--- /dev/null
+++ b/test/script/basic/JDK-8048079_2a.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048079: Persistent code store is broken after optimistic types merge.
+ * Same script as JDK-8048079_1a.js to exercise code cache.
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'prototype.js');
diff --git a/test/script/basic/JDK-8048079_2a.js.EXPECTED b/test/script/basic/JDK-8048079_2a.js.EXPECTED
new file mode 100644
index 00000000..e677550c
--- /dev/null
+++ b/test/script/basic/JDK-8048079_2a.js.EXPECTED
@@ -0,0 +1 @@
+parsed and compiled ok prototype.js
diff --git a/test/script/basic/JDK-8048079_2b.js b/test/script/basic/JDK-8048079_2b.js
new file mode 100644
index 00000000..60287a24
--- /dev/null
+++ b/test/script/basic/JDK-8048079_2b.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048079: Persistent code store is broken after optimistic types merge
+ * Same script as JDK-8048079_1b.js to exercise code cache again.
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
diff --git a/test/script/basic/JDK-8048079_2b.js.EXPECTED b/test/script/basic/JDK-8048079_2b.js.EXPECTED
new file mode 100644
index 00000000..28dd1b9d
--- /dev/null
+++ b/test/script/basic/JDK-8048079_2b.js.EXPECTED
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/test/script/basic/JDK-8048505.js b/test/script/basic/JDK-8048505.js
new file mode 100644
index 00000000..4ee8fe16
--- /dev/null
+++ b/test/script/basic/JDK-8048505.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Read fully parameter test
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+var str = __FILE__;
+var first = readFully(str);
+print(typeof str);
+
+var str2 = __FILE__.substring(0,5);
+var str3 = __FILE__.substring(5);
+print(typeof str2);
+print(typeof str3);
+
+var cons = str2 + str3;
+print(typeof cons);
+
+var second = readFully(cons);
+
+var f = new java.io.File(str);
+print(typeof f);
+var third = readFully(f);
+
+print(first.length() == second.length());
+print(first.length() == third.length());
+
diff --git a/test/script/basic/JDK-8048505.js.EXPECTED b/test/script/basic/JDK-8048505.js.EXPECTED
new file mode 100644
index 00000000..ed5daae8
--- /dev/null
+++ b/test/script/basic/JDK-8048505.js.EXPECTED
@@ -0,0 +1,7 @@
+string
+string
+string
+string
+object
+true
+true
diff --git a/test/script/basic/JDK-8048586.js b/test/script/basic/JDK-8048586.js
new file mode 100644
index 00000000..a55299a0
--- /dev/null
+++ b/test/script/basic/JDK-8048586.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048586: String concatenation with optimistic types is slow
+ *
+ * @test
+ * @run
+ */
+
+var body = '';
+
+for (var i = 0; i < 1024 * 1024; i++) {
+ body += 'hello world\n';
+}
+
+body = '';
+
+for (var i = 0; i < 1024 * 1024; i++) {
+ body = body + 'hello world\n';
+}
diff --git a/test/script/basic/JDK-8048718.js b/test/script/basic/JDK-8048718.js
new file mode 100644
index 00000000..08b0e3f8
--- /dev/null
+++ b/test/script/basic/JDK-8048718.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8048718: JSON.parse('{"0":0, "64":0}') throws ArrayindexOutOfBoundsException
+ *
+ * @test
+ * @run
+ */
+
+var obj = JSON.parse('{"0":0, "64":0}');
+if ("1" in obj) {
+ fail("found element at index 1");
+}
+
+if ("63" in obj) {
+ fail("found element at index 63");
+}
+
+if (obj[0] != 0) {
+ fail("expected obj[0] to be 0");
+}
+
+if (obj[64] != 0) {
+ fail("expected obj[64] to be 0");
+}
+
+for (var i in obj) {
+ if (i != "0" && i != "64") {
+ fail("invalid property " + i);
+ }
+}
diff --git a/test/script/basic/JDK-8049086.js b/test/script/basic/JDK-8049086.js
new file mode 100644
index 00000000..da4a9627
--- /dev/null
+++ b/test/script/basic/JDK-8049086.js
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8049086: Minor API convenience functions on "Java" object
+ *
+ * @test
+ * @run
+ */
+
+var System = Java.type("java.lang.System");
+var out = System.out;
+var println = out.println;
+var getProperty = System.getProperty;
+var File = Java.type("java.io.File")["(String)"];
+
+print("println is java method? " + Java.isJavaMethod(println));
+print("println is script function? " + Java.isScriptFunction(println));
+print("getProperty is java method? " + Java.isJavaMethod(getProperty));
+print("getProperty is script function? " + Java.isScriptFunction(getProperty));
+print("File is java method? " + Java.isJavaMethod(File));
+print("File is script function? " + Java.isScriptFunction(File));
+
+print("eval is script function? " + Java.isScriptFunction(eval));
+print("eval is java method? " + Java.isJavaMethod(eval));
+function hello() {}
+print("hello is script function? " + Java.isScriptFunction(hello));
+print("hello is java method? " + Java.isJavaMethod(hello));
+
+print("out is script object? " + Java.isScriptObject(out));
+print("System is script object? " + Java.isScriptObject(System));
+print("Object is script object? " + Java.isScriptObject(Object));
+print("{} is script object? " + Java.isScriptObject({}));
+print("/foo/ is script object? " + Java.isScriptObject(/foo/));
+
+// Java function is anything whose 'typeof' is 'function' but it is not
+// a script function! This includes:
+// (a) Java methods (b) Java classes (as these respond to new)
+// (c) FunctionalInterface objects (d) JSObjects that are 'functions'
+
+print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
+print("java.lang.Runnable instance is java function? "
+ + Java.isJavaFunction(new java.lang.Runnable(function() {})));
+print("eval is java function? " + Java.isJavaFunction(eval));
+print("println is java function? " + Java.isJavaFunction(println));
+print("getProperty is java function? " + Java.isJavaFunction(getProperty));
+
+var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
+print("callable JSObject is function? " +
+ Java.isJavaFunction(new JSObject() {
+ isFunction: function() true,
+ call: function() {}
+ })
+);
+
+print("Non callable JSObject is function? " +
+ Java.isJavaFunction(new JSObject() {
+ isFunction: function() false,
+ })
+);
+
+// synchronized function
+var lock = new java.lang.Object();
+
+print("lock is java object? " + Java.isJavaObject(lock));
+print("eval is java object? " + Java.isJavaObject(eval));
+print("{} is java object? " + Java.isJavaObject({}));
+print("/foo/ is java object? " + Java.isJavaObject(/foo/));
+print("[] is java object? " + Java.isJavaObject([]));
+print("java.io.File is java object? " + Java.isJavaObject(java.io.File));
+
+// synchornized function checks
+Java.synchronized(function() {
+ var th = new java.lang.Thread(Java.synchronized(function() {
+ print("new thread");
+ print("notifying..");
+ lock.notifyAll();
+ }, lock));
+ th.start();
+ print("about to wait..");
+ lock.wait();
+ th.join();
+ print("done waiting!");
+}, lock)();
+
+// try Mozilla "sync" as well
+load("nashorn:mozilla_compat.js");
+sync(function() {
+ var th = new java.lang.Thread(sync(function() {
+ print("new thread");
+ print("notifying..");
+ lock.notifyAll();
+ }, lock));
+ th.start();
+ print("about to wait..");
+ lock.wait();
+ th.join();
+ print("done waiting!");
+}, lock)();
+
+function expectTypeError(func) {
+ try {
+ func();
+ throw new Error("should have thrown TypeError");
+ } catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("Expected TypeError, got " +e);
+ }
+ print(e);
+ }
+}
+
+expectTypeError(function() Java.synchronized(232));
+expectTypeError(function() sync(232));
+expectTypeError(function() Java.synchronized({}));
+expectTypeError(function() sync({}));
+expectTypeError(function() Java.synchronized([]));
+expectTypeError(function() sync([]));
+expectTypeError(function() Java.synchronized("hello"));
+expectTypeError(function() sync("hello"));
+expectTypeError(function() Java.synchronized(null));
+expectTypeError(function() sync(null));
+expectTypeError(function() Java.synchronized(undefined));
+expectTypeError(function() sync(undefined));
diff --git a/test/script/basic/JDK-8049086.js.EXPECTED b/test/script/basic/JDK-8049086.js.EXPECTED
new file mode 100644
index 00000000..d67db5da
--- /dev/null
+++ b/test/script/basic/JDK-8049086.js.EXPECTED
@@ -0,0 +1,48 @@
+println is java method? true
+println is script function? false
+getProperty is java method? true
+getProperty is script function? false
+File is java method? true
+File is script function? false
+eval is script function? true
+eval is java method? false
+hello is script function? true
+hello is java method? false
+out is script object? false
+System is script object? false
+Object is script object? true
+{} is script object? true
+/foo/ is script object? true
+java.awt.Color is java function? true
+java.lang.Runnable instance is java function? true
+eval is java function? false
+println is java function? true
+getProperty is java function? true
+callable JSObject is function? true
+Non callable JSObject is function? false
+lock is java object? true
+eval is java object? false
+{} is java object? false
+/foo/ is java object? false
+[] is java object? false
+java.io.File is java object? true
+about to wait..
+new thread
+notifying..
+done waiting!
+about to wait..
+new thread
+notifying..
+done waiting!
+TypeError: 232 is not a function
+TypeError: 232 is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Array] is not a function
+TypeError: [object Array] is not a function
+TypeError: hello is not a function
+TypeError: hello is not a function
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: undefined is not a function
+TypeError: undefined is not a function
diff --git a/test/script/basic/JDK-8049242.js b/test/script/basic/JDK-8049242.js
new file mode 100644
index 00000000..3e803b3e
--- /dev/null
+++ b/test/script/basic/JDK-8049242.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8049242: Explicit constructor overload selection should work with StaticClass as well
+ *
+ * @test
+ * @run
+ */
+
+// call explicit constructor
+print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255));
+// print the constructor itself
+print(Java.type("java.awt.Color")["(int,int,int)"]);
+
+// store constructor to call later
+var Color = Java.type("java.awt.Color")["(int,int,int)"];
+// call stored constructor
+print(new Color(33, 233, 2))
+
+// check if default constructor works
+var obj = new (Java.type("java.lang.Object")["()"])();
+if (obj.class != Java.type("java.lang.Object").class) {
+ fail("obj is a java.lang.Object");
+}
+
+// expected failure cases.
+function checkIt(func) {
+ try {
+ func();
+ throw new Error("should have thrown TypeError");
+ } catch(e) {
+ if (! (e instanceof TypeError)) {
+ fail("Expected TypeError, got " + e);
+ }
+ print(e);
+ }
+}
+
+// garbage signature string
+checkIt(function() new (Java.type("java.lang.Object")["()xxxxx"])());
+checkIt(function() new (Java.type("java.lang.Object")["("])());
+checkIt(function() new (Java.type("java.lang.Object")[")"])());
+
+// call constructor as normal method (without 'new')
+checkIt(function() Color());
+
+// try constructor on interface
+checkIt(function() new (Java.type("java.lang.Runnable"))["()"]);
+checkIt(function() new (Java.type("java.lang.Runnable"))["(int)"]);
+
+// try constructor on abstrace class
+try {
+ new (Java.type("java.io.InputStream"))["()"];
+ throw new Error("should have thrown exception!");
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/JDK-8049242.js.EXPECTED b/test/script/basic/JDK-8049242.js.EXPECTED
new file mode 100644
index 00000000..4a2f4169
--- /dev/null
+++ b/test/script/basic/JDK-8049242.js.EXPECTED
@@ -0,0 +1,10 @@
+java.awt.Color[r=255,g=0,b=255]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
+java.awt.Color[r=33,g=233,b=2]
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires "new".
+TypeError: null is not a function
+TypeError: null is not a function
+java.lang.InstantiationException: java.io.InputStream
diff --git a/test/script/basic/JDK-8049407-big-endian.js b/test/script/basic/JDK-8049407-big-endian.js
new file mode 100644
index 00000000..323c4540
--- /dev/null
+++ b/test/script/basic/JDK-8049407-big-endian.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @test
+ * @run
+ * @bigendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "JDK-8049407-payload.js");
diff --git a/test/script/basic/JDK-8049407-big-endian.js.EXPECTED b/test/script/basic/JDK-8049407-big-endian.js.EXPECTED
new file mode 100644
index 00000000..c508d536
--- /dev/null
+++ b/test/script/basic/JDK-8049407-big-endian.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/test/script/basic/JDK-8049407-payload.js b/test/script/basic/JDK-8049407-payload.js
new file mode 100644
index 00000000..467d4bb7
--- /dev/null
+++ b/test/script/basic/JDK-8049407-payload.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @subtest
+ * @run
+ */
+
+var littleEndian = (function() {
+ var buffer = new ArrayBuffer(2);
+ new DataView(buffer).setInt16(0, 256, true);
+ return new Int16Array(buffer)[0] === 256;
+ })();
+
+print(littleEndian);
diff --git a/test/script/basic/JDK-8049407.js b/test/script/basic/JDK-8049407.js
new file mode 100644
index 00000000..4bfcd26c
--- /dev/null
+++ b/test/script/basic/JDK-8049407.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @test
+ * @run
+ * @littleendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "JDK-8049407-payload.js");
diff --git a/test/script/basic/JDK-8049407.js.EXPECTED b/test/script/basic/JDK-8049407.js.EXPECTED
new file mode 100644
index 00000000..27ba77dd
--- /dev/null
+++ b/test/script/basic/JDK-8049407.js.EXPECTED
@@ -0,0 +1 @@
+true
diff --git a/test/script/basic/JDK-8050432.js b/test/script/basic/JDK-8050432.js
new file mode 100644
index 00000000..46d22cf2
--- /dev/null
+++ b/test/script/basic/JDK-8050432.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8050432: javax.script.filename variable should not be enumerable with nashorn engine's ENGINE_SCOPE bindings
+ *
+ * @test
+ * @run
+ */
+
+var ScriptEngine = javax.script.ScriptEngine;
+var m = new javax.script.ScriptEngineManager();
+var engine = m.getEngineByName("nashorn");
+
+engine.put(ScriptEngine.FILENAME, "foo");
+var desc = engine.eval("Object.getOwnPropertyDescriptor(this, '"
+ + ScriptEngine.FILENAME + "')");
+if (desc.enumerable) {
+ fail(ScriptEngine.FILENAME + " is enumerable");
+}
diff --git a/test/script/basic/JDK-8051439.js b/test/script/basic/JDK-8051439.js
new file mode 100644
index 00000000..255803dd
--- /dev/null
+++ b/test/script/basic/JDK-8051439.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051439: Wrong type calculated for ADD operator with undefined operand
+ *
+ * @test
+ * @run
+ */
+
+// Test + operator
+function f1() {
+ var x;
+ for (var i = 0;i < 3; i++) {
+ x = x + i;
+ }
+ x = x + "test";
+ return x;
+}
+
+// Test += operator
+function f2() {
+ var x;
+ for (var i = 0;i < 3; i++) {
+ x += i;
+ }
+ x += "test";
+ return x;
+}
+
+print(f1());
+print(f2());
diff --git a/test/script/basic/JDK-8051439.js.EXPECTED b/test/script/basic/JDK-8051439.js.EXPECTED
new file mode 100644
index 00000000..5c0f70f1
--- /dev/null
+++ b/test/script/basic/JDK-8051439.js.EXPECTED
@@ -0,0 +1,2 @@
+NaNtest
+NaNtest
diff --git a/test/script/basic/JDK-8051778.js b/test/script/basic/JDK-8051778.js
new file mode 100644
index 00000000..2d8d788a
--- /dev/null
+++ b/test/script/basic/JDK-8051778.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051778: support bind on all Nashorn callables
+ *
+ * @test
+ * @run
+ */
+
+var bind = Function.prototype.bind;
+
+// Bind a POJO method
+var l = new java.util.ArrayList();
+var l_add_foo = bind.call(l.add, l, "foo");
+l_add_foo();
+print("l=" + l);
+
+// Bind a BoundCallable
+var l_add = bind.call(l.add, l);
+var l_add_foo2 = bind.call(l_add, null, "foo2");
+l_add_foo2();
+print("l=" + l);
+
+// Bind a POJO method retrieved from one instance to a different but
+// compatible instance.
+var l2 = new java.util.ArrayList();
+var l2_size = bind.call(l.size, l2);
+print("l2_size()=" + l2_size());
+
+// Bind a Java type object (used as a constructor).
+var construct_two = bind.call(java.lang.Integer, null, 2);
+print("Bound Integer(2) constructor: " + new construct_two())
+
+// Bind a @FunctionalInterface proxying to an object literal. NOTE: the
+// expected value of this.a is always "original" and never "bound". This
+// might seem counterintuitive, but we are not binding the apply()
+// function of the object literal that defines the BiFunction behaviour,
+// we are binding the SAM proxy object instead, and it is always
+// forwarding to the apply() function with "this" set to the object
+// literal. Basically, binding "this" for SAM proxies is useless; only
+// binding arguments makes sense.
+var f1 = new java.util.function.BiFunction() {
+ apply: function(x, y) {
+ return "BiFunction with literal: " + this.a + ", " + x + ", " + y;
+ },
+ a: "unbound"
+};
+print((bind.call(f1, {a: "bound"}))(1, 2))
+print((bind.call(f1, {a: "bound"}, 3))(4))
+print((bind.call(f1, {a: "bound"}, 5, 6))())
+
+// Bind a @FunctionalInterface proxying to a function. With the same
+// reasoning as above (binding the proxy vs. binding the JS function),
+// the value of this.a will always be undefined, and never "bound".
+var f2 = new java.util.function.BiFunction(
+ function(x, y) {
+ return "BiFunction with function: " + this.a + ", " + x + ", " + y;
+ }
+);
+print((bind.call(f2, {a: "bound"}))(7, 8))
+print((bind.call(f2, {a: "bound"}, 9))(10))
+print((bind.call(f2, {a: "bound"}, 11, 12))())
diff --git a/test/script/basic/JDK-8051778.js.EXPECTED b/test/script/basic/JDK-8051778.js.EXPECTED
new file mode 100644
index 00000000..4ba3e287
--- /dev/null
+++ b/test/script/basic/JDK-8051778.js.EXPECTED
@@ -0,0 +1,10 @@
+l=[foo]
+l=[foo, foo2]
+l2_size()=0
+Bound Integer(2) constructor: 2
+BiFunction with literal: unbound, 1, 2
+BiFunction with literal: unbound, 3, 4
+BiFunction with literal: unbound, 5, 6
+BiFunction with function: undefined, 7, 8
+BiFunction with function: undefined, 9, 10
+BiFunction with function: undefined, 11, 12
diff --git a/test/script/basic/JDK-8054503.js b/test/script/basic/JDK-8054503.js
new file mode 100644
index 00000000..d11c6cd8
--- /dev/null
+++ b/test/script/basic/JDK-8054503.js
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * 8054503: test/script/external/test262/test/suite/ch12/12.6/12.6.4/12.6.4-2.js fails with tip
+ *
+ * @test
+ * @run
+ */
+
+function MyFunc() {}
+
+MyFunc.prototype.foo = 42;
+var obj = new MyFunc();
+Object.defineProperty(obj, "foo", {
+ value: "hello",
+ enumerable: false
+});
+
+for (var p in obj) {
+ if (p == "foo") {
+ fail("'foo' is not expected here!");
+ }
+}
+
+for each (var p in obj) {
+ if (p == "hello" || p == 42) {
+ fail("'foo' value is not expected here");
+ }
+}
diff --git a/test/script/basic/JDK-8055762.js b/test/script/basic/JDK-8055762.js
new file mode 100644
index 00000000..e772a579
--- /dev/null
+++ b/test/script/basic/JDK-8055762.js
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055762: Nashorn misses linker for netscape.javascript.JSObject instances
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// basic checks for special linkage for netscape.javascript.JSObject
+// instances. For this test, we just subclass that class rather than
+// involve actual browser script engine or javafx webkit objects.
+
+function main() {
+ var JSObject;
+ try {
+ JSObject = Java.type("netscape.javascript.JSObject");
+ } catch (e) {
+ if (e instanceof java.lang.ClassNotFoundException) {
+ // pass vacuously by emitting the .EXPECTED file content
+ var str = readFully(__DIR__ + "JDK-8055762.js.EXPECTED");
+ print(str.substring(0, str.length - 1));
+ return;
+ } else{
+ fail("unexpected exception for JSObject", e);
+ }
+ }
+ test(JSObject);
+}
+
+function test(JSObject) {
+ var obj = new (Java.extend(JSObject))() {
+ getMember: function(name) {
+ if (name == "func") {
+ return function(arg) {
+ print("func called with " + arg);
+ }
+ }
+ return name.toUpperCase();
+ },
+
+ getSlot: function(index) {
+ return index^2;
+ },
+
+ setMember: function(name, value) {
+ print(name + " set to " + value);
+ },
+
+ setSlot: function(index, value) {
+ print("[" + index + "] set to " + value);
+ }
+ };
+
+ print(obj["foo"]);
+ print(obj[2]);
+ obj.bar = 23;
+ obj[3] = 23;
+ obj.func("hello");
+}
+
+main();
diff --git a/test/script/basic/JDK-8055762.js.EXPECTED b/test/script/basic/JDK-8055762.js.EXPECTED
new file mode 100644
index 00000000..51a02015
--- /dev/null
+++ b/test/script/basic/JDK-8055762.js.EXPECTED
@@ -0,0 +1,5 @@
+FOO
+0
+bar set to 23
+[3] set to 23
+func called with hello
diff --git a/test/script/basic/JDK-8055796.js b/test/script/basic/JDK-8055796.js
new file mode 100644
index 00000000..6728ff7f
--- /dev/null
+++ b/test/script/basic/JDK-8055796.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055796: JSObject and browser JSObject linkers should provide fallback to call underlying Java methods directly
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+var jsobj = e.eval("({ foo: 33, valueOf: function() 42 })");
+
+print("foo =", jsobj['getMember(java.lang.String)']("foo"));
+print("eval =", jsobj['eval(String)']("this + 44"));
+print("valueOf function? =", (jsobj.valueOf)['isFunction()']());
diff --git a/test/script/basic/JDK-8055796.js.EXPECTED b/test/script/basic/JDK-8055796.js.EXPECTED
new file mode 100644
index 00000000..6ea45924
--- /dev/null
+++ b/test/script/basic/JDK-8055796.js.EXPECTED
@@ -0,0 +1,3 @@
+foo = 33
+eval = 86
+valueOf function? = true
diff --git a/test/script/basic/JDK-8055796_2.js b/test/script/basic/JDK-8055796_2.js
new file mode 100644
index 00000000..d547a0ab
--- /dev/null
+++ b/test/script/basic/JDK-8055796_2.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055796: JSObject and browser JSObject linkers should provide fallback to call underlying Java methods directly
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function main() {
+ var JSObject;
+ try {
+ JSObject = Java.type("netscape.javascript.JSObject");
+ } catch (e) {
+ if (e instanceof java.lang.ClassNotFoundException) {
+ // pass vacuously by emitting the .EXPECTED file content
+ var str = readFully(__DIR__ + "JDK-8055796_2.js.EXPECTED");
+ print(str.substring(0, str.length - 1));
+ return;
+ } else {
+ fail("unexpected exception on JSObject", e);
+ }
+ }
+ test(JSObject);
+}
+
+function test(JSObject) {
+ var bjsobj = new (Java.extend(JSObject))() {
+ getMember: function(name) {
+ if (name == "func") {
+ return function(arg) {
+ print("func called with " + arg);
+ }
+ }
+ return name.toUpperCase();
+ },
+
+ getSlot: function(index) {
+ return index*index;
+ },
+
+ setMember: function(name, value) {
+ print(name + " set to " + value);
+ },
+
+ setSlot: function(index, value) {
+ print("[" + index + "] set to " + value);
+ }
+ };
+
+ print("getMember('foo') =", bjsobj['getMember(String)']('foo'));
+ print("getSlot(6) =", bjsobj['getSlot(int)'](6));
+ bjsobj['setMember(String, Object)']('bar', 'hello');
+ bjsobj['setSlot(int, Object)'](10, 42);
+}
+
+main();
diff --git a/test/script/basic/JDK-8055796_2.js.EXPECTED b/test/script/basic/JDK-8055796_2.js.EXPECTED
new file mode 100644
index 00000000..dbb37569
--- /dev/null
+++ b/test/script/basic/JDK-8055796_2.js.EXPECTED
@@ -0,0 +1,4 @@
+getMember('foo') = FOO
+getSlot(6) = 36
+bar set to hello
+[10] set to 42
diff --git a/test/script/basic/JDK-8055870.js b/test/script/basic/JDK-8055870.js
new file mode 100644
index 00000000..dc308408
--- /dev/null
+++ b/test/script/basic/JDK-8055870.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055870: iteration fails if index var is not used
+ *
+ * @test
+ * @run
+ */
+
+function isEmpty2(v) {
+ for (var k in v) {
+ return false;
+ }
+ return true;
+}
+
+x = {test: 'test'}
+
+print(isEmpty2(x))
+
diff --git a/test/script/basic/JDK-8055870.js.EXPECTED b/test/script/basic/JDK-8055870.js.EXPECTED
new file mode 100644
index 00000000..c508d536
--- /dev/null
+++ b/test/script/basic/JDK-8055870.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/test/script/basic/JDK-8056123.js b/test/script/basic/JDK-8056123.js
new file mode 100644
index 00000000..08b2a6b6
--- /dev/null
+++ b/test/script/basic/JDK-8056123.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8056123: Anonymous function statements leak internal function names into global scope
+ *
+ * @test
+ * @run
+ */
+
+// do *not* introduce newlines before this line!
+function () { // line 32
+ print("hello function!");
+}
+
+if (typeof this["L:32"] != 'undefined') {
+ fail("anonymous function statement leaks name in global");
+}
+
+var keys = Object.keys(this);
+for (var i in keys) {
+ if (keys[i].contains("L:")) {
+ fail("found " + keys[i] + " in global scope");
+ }
+}
diff --git a/test/script/basic/JDK-8056129.js b/test/script/basic/JDK-8056129.js
new file mode 100644
index 00000000..cbf8df3c
--- /dev/null
+++ b/test/script/basic/JDK-8056129.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8056129: AtomicInteger is treated as primitive number with optimistic compilation
+ *
+ * @test
+ * @run
+ */
+
+var AtomicInteger = java.util.concurrent.atomic.AtomicInteger;
+
+function getAtomic() {
+ return new AtomicInteger()
+}
+var x = getAtomic()
+print(x instanceof AtomicInteger)
+
+var a = []
+a.push(x)
+var y = a[0]
+print(y instanceof AtomicInteger)
diff --git a/test/script/basic/JDK-8056129.js.EXPECTED b/test/script/basic/JDK-8056129.js.EXPECTED
new file mode 100644
index 00000000..bb101b64
--- /dev/null
+++ b/test/script/basic/JDK-8056129.js.EXPECTED
@@ -0,0 +1,2 @@
+true
+true
diff --git a/test/script/basic/JDK-8056978.js b/test/script/basic/JDK-8056978.js
new file mode 100644
index 00000000..1b3577d4
--- /dev/null
+++ b/test/script/basic/JDK-8056978.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8056978: ClassCastException: cannot cast jdk.nashorn.internal.scripts.JO*
+ *
+ * @test
+ * @run
+ */
+
+var obj1 = {
+ 'name': 'test name',
+ '1': '1',
+ '2': '2',
+ '3': '3',
+ '4': '4',
+ '5': '5'
+};
+
+var obj2 = {
+ 'name': 'hello'
+};
+
+print(obj2['name']);
+print(obj2.name);
+
diff --git a/test/script/basic/JDK-8056978.js.EXPECTED b/test/script/basic/JDK-8056978.js.EXPECTED
new file mode 100644
index 00000000..317e9677
--- /dev/null
+++ b/test/script/basic/JDK-8056978.js.EXPECTED
@@ -0,0 +1,2 @@
+hello
+hello
diff --git a/test/script/basic/JDK-8057019-2.js b/test/script/basic/JDK-8057019-2.js
new file mode 100644
index 00000000..416acba9
--- /dev/null
+++ b/test/script/basic/JDK-8057019-2.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * this apply with extra arguments
+ * (with apply to call enabled)
+ *
+ * @test
+ * @run
+ */
+
+load(__DIR__ + 'JDK-8057019-payload.js');
+
diff --git a/test/script/basic/JDK-8057019-2.js.EXPECTED b/test/script/basic/JDK-8057019-2.js.EXPECTED
new file mode 100644
index 00000000..34587ced
--- /dev/null
+++ b/test/script/basic/JDK-8057019-2.js.EXPECTED
@@ -0,0 +1,24 @@
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
diff --git a/test/script/basic/JDK-8057019-payload.js b/test/script/basic/JDK-8057019-payload.js
new file mode 100644
index 00000000..e62e51fa
--- /dev/null
+++ b/test/script/basic/JDK-8057019-payload.js
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * this apply with extra arguments
+ *
+ * @subtest
+ */
+
+function func(x, y, z) {
+ print(x, y, z);
+}
+
+function g() {
+ func.apply(this, arguments);
+}
+function h() {
+ func.apply(this, arguments, 23);
+}
+function i() {
+ func.apply(this, arguments, 23, 4711);
+}
+function j() {
+ func.apply(this, arguments, 23, 4711, "apa", "dingo", "gorilla");
+}
+function k() {
+ func.apply(this, arguments, 23);
+}
+function l() {
+ func.apply(this, [23, "apa", "gorilla", "dingo"], 17);
+}
+function m() {
+ func.apply(this, [23, "apa", "gorilla", "dingo"]);
+}
+function n() {
+ func.apply(this, "significant");
+}
+
+g(1,2);
+g(1,2,3);
+g(1,2,3,4);
+
+h(1,2);
+h(1,2,3);
+h(1,2,3,4);
+
+i(1,2);
+i(1,2,3);
+i(1,2,3,4);
+
+j(1,2);
+j(1,2,3);
+j(1,2,3,4);
+
+k(1,2);
+k(1,2,3);
+k(1,2,3,4);
+
+l(1,2);
+l(1,2,3);
+l(1,2,3,4);
+
+m(1,2);
+m(1,2,3);
+m(1,2,3,4);
+
+try {
+ n(1,2);
+} catch (e) {
+ print(e);
+}
+try {
+ n(1,2,3);
+} catch (e) {
+ print(e);
+}
+
+try {
+ n(1,2,3,4);
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/JDK-8057019.js b/test/script/basic/JDK-8057019.js
new file mode 100644
index 00000000..16b308e0
--- /dev/null
+++ b/test/script/basic/JDK-8057019.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * this apply with extra arguments
+ * (turning off apply to call)
+ *
+ * @fork
+ * @option -Dnashorn.apply2call=false
+ * @test
+ * @run
+ */
+
+load(__DIR__ + 'JDK-8057019-payload.js');
+
diff --git a/test/script/basic/JDK-8057019.js.EXPECTED b/test/script/basic/JDK-8057019.js.EXPECTED
new file mode 100644
index 00000000..34587ced
--- /dev/null
+++ b/test/script/basic/JDK-8057019.js.EXPECTED
@@ -0,0 +1,24 @@
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+1 2 undefined
+1 2 3
+1 2 3
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+23 apa gorilla
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
+TypeError: Function.prototype.apply expects an Array for second argument
diff --git a/test/script/basic/JDK-8057825.js b/test/script/basic/JDK-8057825.js
new file mode 100644
index 00000000..256e2fbf
--- /dev/null
+++ b/test/script/basic/JDK-8057825.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057825 : A failed apply to call generation should NOT reuse the
+ * best apply to call generation so far - because it may not fit!!!
+ *
+ * @test
+ * @run
+ */
+
+function createApplier(f) {
+ function applier() {
+ f.apply(this, arguments); // no transform applied here
+ }
+ return applier;
+}
+
+function printer(x,y) {
+ print(x + " and " + y);
+}
+
+var printerApplier = createApplier(printer);
+printerApplier();
+printerApplier.apply(this, ["foo", "bar"]);
diff --git a/test/script/basic/JDK-8057825.js.EXPECTED b/test/script/basic/JDK-8057825.js.EXPECTED
new file mode 100644
index 00000000..87acc7c4
--- /dev/null
+++ b/test/script/basic/JDK-8057825.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined and undefined
+foo and bar
diff --git a/test/script/basic/JDK-8058179.js b/test/script/basic/JDK-8058179.js
new file mode 100644
index 00000000..1ecd823d
--- /dev/null
+++ b/test/script/basic/JDK-8058179.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058179: Global constants get in the way of self-modifying properties
+ *
+ * @test
+ * @run
+ */
+
+var global = this;
+
+Object.defineProperty(global, "value", {
+ get: function() {
+ print("getting value");
+ global["value"] = "value 2";
+ return "value 1";
+ },
+ set: function(value) {
+ print("setting value: " + value);
+ delete global["value"];
+ global["value"] = value;
+ },
+ configurable: true
+});
+
+print(value);
+print(value);
diff --git a/test/script/basic/JDK-8058179.js.EXPECTED b/test/script/basic/JDK-8058179.js.EXPECTED
new file mode 100644
index 00000000..6d8ed6f6
--- /dev/null
+++ b/test/script/basic/JDK-8058179.js.EXPECTED
@@ -0,0 +1,4 @@
+getting value
+setting value: value 2
+value 1
+value 2
diff --git a/test/script/basic/JDK-8058422.js b/test/script/basic/JDK-8058422.js
new file mode 100644
index 00000000..b15c7cfb
--- /dev/null
+++ b/test/script/basic/JDK-8058422.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058422: Users should be able to overwrite "context" and "engine" variables
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+e.put("foo", "hello");
+var obj = e.eval("context.getAttribute('foo')");
+if (obj != "hello") {
+ fail("Expected 'obj' to be 'hello'");
+}
+
+e.put("context", "bar");
+if (e.eval("context") != "bar") {
+ fail("Expected 'context' to be 'bar'");
+}
+
+if (e.eval("foo") != "hello") {
+ fail("Expected 'foo' to be 'hello'");
+}
+
+if (e.eval("engine") != e) {
+ fail("'engine' is not evaluaed to current engine");
+}
+
+e.put("engine", "foobar");
+if (e.eval("engine") != "foobar") {
+ fail("'engine' is not evalued to 'foobar'");
+}
diff --git a/test/script/basic/JDK-8058545.js b/test/script/basic/JDK-8058545.js
new file mode 100644
index 00000000..3b3a7c60
--- /dev/null
+++ b/test/script/basic/JDK-8058545.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058545: With strict mode, bean property assignment of a non-existent property should result in TypeError
+ *
+ * @test
+ * @run
+ */
+
+'use strict';
+var File = Java.type("java.io.File");
+var f = new File(".");
+try {
+ f.foo = 33;
+ fail("Should have thrown TypeError");
+} catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("Expected TypeError, got " + e);
+ }
+}
diff --git a/test/script/basic/JDK-8058561.js b/test/script/basic/JDK-8058561.js
new file mode 100644
index 00000000..f27d1d1b
--- /dev/null
+++ b/test/script/basic/JDK-8058561.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058561: NPE in LocalVariableTypesCalculator
+ *
+ * @test
+ * @run
+ * @option --lazy-compilation=false
+ */
+
+// Just attempting to compile this caused the NPE
+function func(x, y) {
+ while(true) {
+ switch (y[0]) {
+ case "bar":
+ x = 'xxx';
+ break;
+ }
+ }
+ return x;
+}
diff --git a/test/script/basic/JDK-8058610.js b/test/script/basic/JDK-8058610.js
new file mode 100644
index 00000000..47078c0c
--- /dev/null
+++ b/test/script/basic/JDK-8058610.js
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058610: must not let long operations overflow
+ *
+ * @test
+ * @run
+ */
+
+function mul(x) {
+ return x.foo * x.bar;
+}
+print("=== mul ===")
+print(mul({foo: 2147483647, bar: 2147483647})); // 2^31
+print(mul({foo: 17179869184, bar: 2147483647})); // 2^34
+
+function self_mul(x) {
+ return x.foo *= x.bar;
+}
+print("=== self_mul ===")
+print(self_mul({foo: 2147483647, bar: 2147483647})); // 2^31
+print(self_mul({foo: 17179869184, bar: 2147483647})); // 2^34
+
+// We'll need to use this function to obtain long values larger in
+// magnitude than those precisely representable in a double (2^53),
+// as Nashorn's parser will reify such literals as a double. For
+// overflow on add and sub we need (2^63)-1.
+var parseLong = Java.type("java.lang.Long").parseLong;
+
+function sub(x) {
+ return x.foo - x.bar;
+}
+print("=== sub ===")
+print(sub({foo: 2147483647, bar: -2147483647})); // 2^31
+print(sub({foo: parseLong("9223372036854775807"), bar: parseLong("-9223372036854775807")})); // 2^63-1
+
+function self_sub(x) {
+ return x.foo -= x.bar;
+}
+print("=== self_sub ===")
+print(self_sub({foo: 2147483647, bar: -2147483647})); // 2^31
+print(self_sub({foo: parseLong("9223372036854775807"), bar: parseLong("-9223372036854775807")})); // 2^63-1
+
+function add(x) {
+ return x.foo + x.bar;
+}
+print("=== add ===")
+print(add({foo: 2147483647, bar: 2147483647})); // 2^31
+print(add({foo: parseLong("9223372036854775807"), bar: parseLong("9223372036854775807")})); // 2^63-1
+
+function self_add(x) {
+ return x.foo += x.bar;
+}
+print("=== self_add ===")
+print(self_add({foo: 2147483647, bar: 2147483647})); // 2^31
+print(self_add({foo: parseLong("9223372036854775807"), bar: parseLong("9223372036854775807")})); // 2^63-1
diff --git a/test/script/basic/JDK-8058610.js.EXPECTED b/test/script/basic/JDK-8058610.js.EXPECTED
new file mode 100644
index 00000000..d9d39915
--- /dev/null
+++ b/test/script/basic/JDK-8058610.js.EXPECTED
@@ -0,0 +1,18 @@
+=== mul ===
+4611686014132420600
+36893488130239234000
+=== self_mul ===
+4611686014132420600
+36893488130239234000
+=== sub ===
+4294967294
+18446744073709552000
+=== self_sub ===
+4294967294
+18446744073709552000
+=== add ===
+4294967294
+18446744073709552000
+=== self_add ===
+4294967294
+18446744073709552000
diff --git a/test/script/basic/JDK-8058615.js b/test/script/basic/JDK-8058615.js
new file mode 100644
index 00000000..354b5e4b
--- /dev/null
+++ b/test/script/basic/JDK-8058615.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8058615: Overload resolution ambiguity involving ConsString
+ *
+ * @test
+ * @run
+ */
+
+var strw = new java.io.StringWriter();
+var bufw = new java.io.BufferedWriter(strw);
+var s = "hello ";
+bufw.write(s + "world");
+bufw.close();
+print(strw.toString());
diff --git a/test/script/basic/JDK-8058615.js.EXPECTED b/test/script/basic/JDK-8058615.js.EXPECTED
new file mode 100644
index 00000000..3b18e512
--- /dev/null
+++ b/test/script/basic/JDK-8058615.js.EXPECTED
@@ -0,0 +1 @@
+hello world
diff --git a/test/script/basic/JDK-8059443.js b/test/script/basic/JDK-8059443.js
new file mode 100644
index 00000000..e0d2b0f8
--- /dev/null
+++ b/test/script/basic/JDK-8059443.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8059443: NPE when unboxing return values
+ *
+ * NOTE: this test can only pass when running with a JDK where
+ * JDK-8060483 is also fixed (9b37 or later).
+ *
+ * @test
+ * @run
+ */
+
+var NullProvider = Java.type("jdk.nashorn.test.models.NullProvider");
+
+if (!NullProvider.getBoolean()) { print("yay"); }
+print(NullProvider.getLong() * (1 << 33));
+print(NullProvider.getDouble() / 2.5);
+print(NullProvider.getInteger() << 1);
diff --git a/test/script/basic/JDK-8059443.js.EXPECTED b/test/script/basic/JDK-8059443.js.EXPECTED
new file mode 100644
index 00000000..dc60c976
--- /dev/null
+++ b/test/script/basic/JDK-8059443.js.EXPECTED
@@ -0,0 +1,4 @@
+yay
+0
+0
+0
diff --git a/test/script/basic/JDK-8060011.js b/test/script/basic/JDK-8060011.js
new file mode 100644
index 00000000..7514ff29
--- /dev/null
+++ b/test/script/basic/JDK-8060011.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8060011: Concatenating an array and converting it to Java gives wrong result
+ *
+ * @test
+ * @run
+ */
+
+
+function compareAsJavaArrays(a1, a2) {
+ var ja1 = Java.to(a1);
+ var ja2 = Java.to(a2);
+ if (ja1.length !== ja2.length) {
+ throw "different length";
+ }
+ for (var i = 0; i < ja1.length; i++) {
+ if (ja1[i] !== ja2[i]) {
+ throw "different element at " + i;
+ }
+ }
+ if (java.util.Arrays.toString(ja1) !== java.util.Arrays.toString(ja2)) {
+ throw "different string representation";
+ }
+}
+
+compareAsJavaArrays([0, 1, 2, 3],
+ [0].concat([1, 2, 3]));
+compareAsJavaArrays([1000000000, 2000000000, 3000000000, 4000000000],
+ [1000000000].concat([2000000000, 3000000000, 4000000000]));
+compareAsJavaArrays([0.5, 1.5, 2.5, 3.5],
+ [0.5].concat([1.5, 2.5, 3.5]));
+compareAsJavaArrays(["0", "1", "2", "3"],
+ ["0"].concat(["1", "2", "3"]));
+
+
+
diff --git a/test/script/basic/JDK-8060101.js b/test/script/basic/JDK-8060101.js
new file mode 100644
index 00000000..617bbccd
--- /dev/null
+++ b/test/script/basic/JDK-8060101.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter
+ *
+ * @test
+ * @run
+ */
+
+var constant = 0.50;
+var ind = 0.0;
+
+// make sure callsites are exercised quite a few times
+// to induce megamorphic callsite for with/JavaImporter
+// combo - which triggered that AssertionError.
+for (var i = 0; i < 50; i++) {
+ var math = new JavaImporter(java.lang.StrictMath);
+ ind += 10.0;
+ with (math) {
+ StrictMath.exp(-constant*ind);
+ }
+}
+
+for (var i = 0; i < 50; i++) {
+ var math = new JavaImporter(java.lang.StrictMath);
+ try {
+ math.Foo();
+ } catch (e) {
+ if (! (e instanceof TypeError)) {
+ throw e;
+ }
+ }
+}
diff --git a/test/script/basic/JDK-8061113.js b/test/script/basic/JDK-8061113.js
new file mode 100644
index 00000000..1cd8b35b
--- /dev/null
+++ b/test/script/basic/JDK-8061113.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8061113: Boolean used as optimistic call return type
+ *
+ * @test
+ * @run
+ */
+
+function testcase() {
+ var a = {x:0};
+ return (function () {return a.x === 0})();
+}
+print(testcase());
diff --git a/test/script/basic/JDK-8061113.js.EXPECTED b/test/script/basic/JDK-8061113.js.EXPECTED
new file mode 100644
index 00000000..27ba77dd
--- /dev/null
+++ b/test/script/basic/JDK-8061113.js.EXPECTED
@@ -0,0 +1 @@
+true
diff --git a/test/script/basic/JDK-8061391.js b/test/script/basic/JDK-8061391.js
new file mode 100644
index 00000000..920efe3e
--- /dev/null
+++ b/test/script/basic/JDK-8061391.js
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8061391 - Checks that the optimistic builtin for concat is semantically
+ * correct.
+ *
+ * @test
+ * @run
+ */
+
+var maxJavaInt = 0x7fffffff;
+
+var ia = [1, 2, 3, 4];
+var la = [maxJavaInt + 1000, maxJavaInt + 2000, maxJavaInt + 3000, maxJavaInt + 4000];
+var da = [1.1, 2.2, 3.3, 4.4];
+var oa = ["one", "two", "three", "four"];
+
+var aa = [ia, la, da, oa];
+
+function concats() {
+ print("shared callsite");
+
+ print(ia);
+ print(la);
+ print(da);
+ print(oa);
+ print(aa);
+
+ for (var i = 0; i < aa.length; i++) {
+ print(aa[i].concat(aa[i][0]));
+ for (var j = 0; j < aa.length ; j++) {
+ print(aa[i].concat(aa[j]));
+ }
+ }
+}
+
+function concats_inline() {
+ print("separate callsites");
+
+ print(ia);
+ print(la);
+ print(da);
+ print(oa);
+ print(aa);
+
+ print(aa[0].concat(aa[0]));
+ print(aa[0].concat(aa[1]));
+ print(aa[0].concat(aa[2]));
+ print(aa[0].concat(aa[3]));
+ print(aa[0].concat(aa[0][0]));
+
+ print(aa[1].concat(aa[0]));
+ print(aa[1].concat(aa[1]));
+ print(aa[1].concat(aa[2]));
+ print(aa[1].concat(aa[3]));
+ print(aa[1].concat(aa[1][0]));
+
+ print(aa[2].concat(aa[0]));
+ print(aa[2].concat(aa[1]));
+ print(aa[2].concat(aa[2]));
+ print(aa[2].concat(aa[3]));
+ print(aa[2].concat(aa[2][0]));
+
+ print(aa[3].concat(aa[0]));
+ print(aa[3].concat(aa[1]));
+ print(aa[3].concat(aa[2]));
+ print(aa[3].concat(aa[3]));
+ print(aa[3].concat(aa[3][0]));
+}
+
+concats();
+concats_inline();
+
+print();
+var oldia = ia.slice(0); //clone ia
+print("oldia = " + oldia);
+ia[10] = "sparse";
+print("oldia = " + oldia);
+
+print();
+print("Redoing with sparse arrays");
+
+concats();
+concats_inline();
+
+ia = oldia;
+print("Restored ia = " + ia);
+
+function concat_expand() {
+ print("concat type expansion");
+ print(ia.concat(la));
+ print(ia.concat(da));
+ print(ia.concat(oa));
+ print(la.concat(ia));
+ print(la.concat(da));
+ print(la.concat(oa));
+ print(da.concat(ia));
+ print(da.concat(la));
+ print(da.concat(oa));
+}
+
+print();
+concat_expand();
+
+print();
+
+function concat_varargs() {
+ print("concat varargs");
+ print(ia.concat(la)); //fast
+ print(ia.concat(la, da, oa)); //slow
+ var slow = ia.concat(1, maxJavaInt * 2, 4711.17, function() { print("hello, world") }); //slow
+ print(slow);
+ return slow;
+}
+
+var slow = concat_varargs();
+
+print();
+print("sanity checks");
+slow.map(
+ function(elem) {
+ if (elem instanceof Function) {
+ elem();
+ } else {
+ print((typeof elem) + " = " + elem);
+ }
+ });
+
+print(ia.concat({key: "value"}));
+print(ia.concat({key: "value"}, {key2: "value2"}));
diff --git a/test/script/basic/JDK-8061391.js.EXPECTED b/test/script/basic/JDK-8061391.js.EXPECTED
new file mode 100644
index 00000000..9b132c3c
--- /dev/null
+++ b/test/script/basic/JDK-8061391.js.EXPECTED
@@ -0,0 +1,138 @@
+shared callsite
+1,2,3,4
+2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4
+one,two,three,four
+1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
+1,2,3,4,1
+1,2,3,4,1,2,3,4
+1,2,3,4,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,1.1,2.2,3.3,4.4
+1,2,3,4,one,two,three,four
+2147484647,2147485647,2147486647,2147487647,2147484647
+2147484647,2147485647,2147486647,2147487647,1,2,3,4
+2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
+2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
+2147484647,2147485647,2147486647,2147487647,one,two,three,four
+1.1,2.2,3.3,4.4,1.1
+1.1,2.2,3.3,4.4,1,2,3,4
+1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
+1.1,2.2,3.3,4.4,one,two,three,four
+one,two,three,four,one
+one,two,three,four,1,2,3,4
+one,two,three,four,2147484647,2147485647,2147486647,2147487647
+one,two,three,four,1.1,2.2,3.3,4.4
+one,two,three,four,one,two,three,four
+separate callsites
+1,2,3,4
+2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4
+one,two,three,four
+1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
+1,2,3,4,1,2,3,4
+1,2,3,4,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,1.1,2.2,3.3,4.4
+1,2,3,4,one,two,three,four
+1,2,3,4,1
+2147484647,2147485647,2147486647,2147487647,1,2,3,4
+2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
+2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
+2147484647,2147485647,2147486647,2147487647,one,two,three,four
+2147484647,2147485647,2147486647,2147487647,2147484647
+1.1,2.2,3.3,4.4,1,2,3,4
+1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
+1.1,2.2,3.3,4.4,one,two,three,four
+1.1,2.2,3.3,4.4,1.1
+one,two,three,four,1,2,3,4
+one,two,three,four,2147484647,2147485647,2147486647,2147487647
+one,two,three,four,1.1,2.2,3.3,4.4
+one,two,three,four,one,two,three,four
+one,two,three,four,one
+
+oldia = 1,2,3,4
+oldia = 1,2,3,4
+
+Redoing with sparse arrays
+shared callsite
+1,2,3,4,,,,,,,sparse
+2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4
+one,two,three,four
+1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
+1,2,3,4,,,,,,,sparse,1
+1,2,3,4,,,,,,,sparse,1,2,3,4,,,,,,,sparse
+1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,,,,,,,sparse,1.1,2.2,3.3,4.4
+1,2,3,4,,,,,,,sparse,one,two,three,four
+2147484647,2147485647,2147486647,2147487647,2147484647
+2147484647,2147485647,2147486647,2147487647,1,2,3,4,,,,,,,sparse
+2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
+2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
+2147484647,2147485647,2147486647,2147487647,one,two,three,four
+1.1,2.2,3.3,4.4,1.1
+1.1,2.2,3.3,4.4,1,2,3,4,,,,,,,sparse
+1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
+1.1,2.2,3.3,4.4,one,two,three,four
+one,two,three,four,one
+one,two,three,four,1,2,3,4,,,,,,,sparse
+one,two,three,four,2147484647,2147485647,2147486647,2147487647
+one,two,three,four,1.1,2.2,3.3,4.4
+one,two,three,four,one,two,three,four
+separate callsites
+1,2,3,4,,,,,,,sparse
+2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4
+one,two,three,four
+1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
+1,2,3,4,,,,,,,sparse,1,2,3,4,,,,,,,sparse
+1,2,3,4,,,,,,,sparse,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,,,,,,,sparse,1.1,2.2,3.3,4.4
+1,2,3,4,,,,,,,sparse,one,two,three,four
+1,2,3,4,,,,,,,sparse,1
+2147484647,2147485647,2147486647,2147487647,1,2,3,4,,,,,,,sparse
+2147484647,2147485647,2147486647,2147487647,2147484647,2147485647,2147486647,2147487647
+2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
+2147484647,2147485647,2147486647,2147487647,one,two,three,four
+2147484647,2147485647,2147486647,2147487647,2147484647
+1.1,2.2,3.3,4.4,1,2,3,4,,,,,,,sparse
+1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4,1.1,2.2,3.3,4.4
+1.1,2.2,3.3,4.4,one,two,three,four
+1.1,2.2,3.3,4.4,1.1
+one,two,three,four,1,2,3,4,,,,,,,sparse
+one,two,three,four,2147484647,2147485647,2147486647,2147487647
+one,two,three,four,1.1,2.2,3.3,4.4
+one,two,three,four,one,two,three,four
+one,two,three,four,one
+Restored ia = 1,2,3,4
+
+concat type expansion
+1,2,3,4,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,1.1,2.2,3.3,4.4
+1,2,3,4,one,two,three,four
+2147484647,2147485647,2147486647,2147487647,1,2,3,4
+2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4
+2147484647,2147485647,2147486647,2147487647,one,two,three,four
+1.1,2.2,3.3,4.4,1,2,3,4
+1.1,2.2,3.3,4.4,2147484647,2147485647,2147486647,2147487647
+1.1,2.2,3.3,4.4,one,two,three,four
+
+concat varargs
+1,2,3,4,2147484647,2147485647,2147486647,2147487647
+1,2,3,4,2147484647,2147485647,2147486647,2147487647,1.1,2.2,3.3,4.4,one,two,three,four
+1,2,3,4,1,4294967294,4711.17,function() { print("hello, world") }
+
+sanity checks
+number = 1
+number = 2
+number = 3
+number = 4
+number = 1
+number = 4294967294
+number = 4711.17
+hello, world
+1,2,3,4,[object Object]
+1,2,3,4,[object Object],[object Object]
diff --git a/test/script/basic/JDK-8061391_2.js b/test/script/basic/JDK-8061391_2.js
new file mode 100644
index 00000000..dff4ab02
--- /dev/null
+++ b/test/script/basic/JDK-8061391_2.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Array extension check
+ *
+ * @test
+ * @run
+ */
+
+"use strict";
+var a = [1,2,3];
+Object.preventExtensions(a);
+try {
+ a[4] = 4;
+ print(a);
+} catch (e) {
+ if (!(e instanceof TypeError)) {
+ print("TypeError expected but got e");
+ }
+}
+
+if (a[0] != 1) {
+ throw "element 0 is wrong";
+}
+if (a[1] != 2) {
+ throw "element 1 is wrong";
+}
+if (a[2] != 3) {
+ throw "element 2 is wrong";
+}
+
diff --git a/test/script/basic/JDK-8061391_3.js b/test/script/basic/JDK-8061391_3.js
new file mode 100644
index 00000000..6648ca51
--- /dev/null
+++ b/test/script/basic/JDK-8061391_3.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Array extension check
+ *
+ * @test
+ * @run
+ */
+
+var a = [1,2,3];
+Object.preventExtensions(a);
+a[4] = 4;
+print(a);
+if (a[0] != 1) {
+ throw "element 0 is wrong";
+}
+if (a[1] != 2) {
+ throw "element 1 is wrong";
+}
+if (a[2] != 3) {
+ throw "element 2 is wrong";
+}
+
diff --git a/test/script/basic/JDK-8061391_3.js.EXPECTED b/test/script/basic/JDK-8061391_3.js.EXPECTED
new file mode 100644
index 00000000..b0246d59
--- /dev/null
+++ b/test/script/basic/JDK-8061391_3.js.EXPECTED
@@ -0,0 +1 @@
+1,2,3
diff --git a/test/script/basic/JDK-8061959.js b/test/script/basic/JDK-8061959.js
new file mode 100644
index 00000000..a234a92b
--- /dev/null
+++ b/test/script/basic/JDK-8061959.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8061959 - Checks for the existence of ArrayBufferView
+ *
+ * @test
+ * @run
+ */
+
+print(ArrayBuffer.isView(new Int8Array(4)));
+print(ArrayBuffer.isView("gorilla"));
+print(ArrayBuffer.isView());
+
+
diff --git a/test/script/basic/JDK-8061959.js.EXPECTED b/test/script/basic/JDK-8061959.js.EXPECTED
new file mode 100644
index 00000000..36bc6136
--- /dev/null
+++ b/test/script/basic/JDK-8061959.js.EXPECTED
@@ -0,0 +1,3 @@
+true
+false
+false
diff --git a/test/script/basic/JDK-8062024.js b/test/script/basic/JDK-8062024.js
new file mode 100644
index 00000000..92085cac
--- /dev/null
+++ b/test/script/basic/JDK-8062024.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062024: Issue with date.setFullYear when time other than midnight
+ *
+ * @test
+ * @option -timezone=Asia/Calcutta
+ * @run
+ */
+
+var date1 = new Date("January 01, 1950 00:00:00");
+print("Before:", date1);
+date1.setFullYear(1960);
+print("After:", date1);
+
+var date2 = new Date("January 01, 1950 00:00:01");
+print("Before:", date2);
+date2.setFullYear(1960);
+print("After:", date2);
diff --git a/test/script/basic/JDK-8062024.js.EXPECTED b/test/script/basic/JDK-8062024.js.EXPECTED
new file mode 100644
index 00000000..ae18fd7d
--- /dev/null
+++ b/test/script/basic/JDK-8062024.js.EXPECTED
@@ -0,0 +1,4 @@
+Before: Sun Jan 01 1950 00:00:00 GMT+0530 (IST)
+After: Fri Jan 01 1960 00:00:00 GMT+0530 (IST)
+Before: Sun Jan 01 1950 00:00:01 GMT+0530 (IST)
+After: Fri Jan 01 1960 00:00:01 GMT+0530 (IST)
diff --git a/test/script/basic/JDK-8062132.js b/test/script/basic/JDK-8062132.js
new file mode 100644
index 00000000..604461df
--- /dev/null
+++ b/test/script/basic/JDK-8062132.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * 8062132: Nashorn incorrectly binds "this" for constructor created by another function
+ *
+ * @test
+ * @run
+ */
+
+function subclass(parentCtor, proto) {
+ function C() {
+ parentCtor.call(this);
+ }
+
+ C.prototype = Object.create(parentCtor.prototype);
+
+ for (var prop in proto) {
+ if (proto.hasOwnProperty(prop)) {
+ C.prototype[prop] = proto[prop];
+ }
+ }
+
+ return C;
+}
+
+var Parent = function() {
+ this.init();
+};
+
+Parent.prototype = {
+ init: null
+};
+
+var Child1 = subclass(Parent, {
+ prop1: 1,
+ init: function() {
+ print('child 1');
+ }
+});
+
+var Child2 = subclass(Parent, {
+ init: function() {
+ print('child 2');
+ }
+});
+
+var Child3 = subclass(Parent, {
+ prop1: 1,
+ init: function() {
+ print('child 3');
+ }
+});
+
+new Child1();
+new Child2();
+new Child3();
+new Child1();
+new Child2();
+new Child3();
diff --git a/test/script/basic/JDK-8062132.js.EXPECTED b/test/script/basic/JDK-8062132.js.EXPECTED
new file mode 100644
index 00000000..96df4080
--- /dev/null
+++ b/test/script/basic/JDK-8062132.js.EXPECTED
@@ -0,0 +1,6 @@
+child 1
+child 2
+child 3
+child 1
+child 2
+child 3
diff --git a/test/script/basic/JDK-8062381.js b/test/script/basic/JDK-8062381.js
new file mode 100644
index 00000000..ef010f79
--- /dev/null
+++ b/test/script/basic/JDK-8062381.js
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062381 wrong argument chosen for charCodeAt in linker logic
+ *
+ * @test
+ * @run
+ */
+
+var s = "abcdef";
+var len = s.length + 1;
+
+function f1() {
+ for (var i = 0; i < len; i++) {
+ print(s.charCodeAt(i));
+ }
+ print(s.charCodeAt());
+}
+
+function f2() {
+ for (var i = 0; i < len; i++) {
+ print(s.charCodeAt("" + i));
+ }
+ print(s.charCodeAt());
+}
+
+f1();
+f2();
+f1();
+f2();
+
+
diff --git a/test/script/basic/JDK-8062381.js.EXPECTED b/test/script/basic/JDK-8062381.js.EXPECTED
new file mode 100644
index 00000000..1692a50b
--- /dev/null
+++ b/test/script/basic/JDK-8062381.js.EXPECTED
@@ -0,0 +1,32 @@
+97
+98
+99
+100
+101
+102
+NaN
+97
+97
+98
+99
+100
+101
+102
+NaN
+97
+97
+98
+99
+100
+101
+102
+NaN
+97
+97
+98
+99
+100
+101
+102
+NaN
+97
diff --git a/test/script/basic/JDK-8062583.js b/test/script/basic/JDK-8062583.js
new file mode 100644
index 00000000..72560b34
--- /dev/null
+++ b/test/script/basic/JDK-8062583.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062583: Throwing object with error prototype causes error proto to be caught
+ *
+ * @test
+ * @run
+ */
+
+function CustomError() {
+ this.name = "CustomError";
+}
+
+CustomError.prototype = new Error();
+
+var c1 = new CustomError();
+
+try {
+ throw c1;
+} catch (e) {
+ print(e === c1);
+ print(e === CustomError.prototype);
+ print(e.stack.replace(/\\/g, '/'));
+ print(e.nashornException.toString().replace(/\\/g, '/'));
+}
+
+var c2 = new CustomError();
+Error.captureStackTrace(c2);
+print(c2.stack.replace(/\\/g, '/'));
+print(c2.nashornException.toString().replace(/\\/g, '/'));
diff --git a/test/script/basic/JDK-8062583.js.EXPECTED b/test/script/basic/JDK-8062583.js.EXPECTED
new file mode 100644
index 00000000..75201739
--- /dev/null
+++ b/test/script/basic/JDK-8062583.js.EXPECTED
@@ -0,0 +1,8 @@
+true
+false
+CustomError
+ at <program> (test/script/basic/JDK-8062583.js:40)
+test/script/basic/JDK-8062583.js:40:4 CustomError
+CustomError
+ at <program> (test/script/basic/JDK-8062583.js:49)
+test/script/basic/JDK-8062583.js:49 CustomError
diff --git a/test/script/basic/JDK-8062624.js b/test/script/basic/JDK-8062624.js
new file mode 100644
index 00000000..c5ecb963
--- /dev/null
+++ b/test/script/basic/JDK-8062624.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062624: java.lang.String methods not available on concatenated strings
+ *
+ * @test
+ * @run
+ */
+
+function testStringMethods(s) {
+ print(s.startsWith("f"));
+ print(s.endsWith("r"));
+ print(Java.from(s.getBytes()));
+ print(Java.from(s.bytes));
+}
+
+var s = "f";
+testStringMethods(s);
+s = s + "oo";
+testStringMethods(s);
+testStringMethods("abc");
+s += "bar";
+s = "baz" + s;
+testStringMethods(s);
diff --git a/test/script/basic/JDK-8062624.js.EXPECTED b/test/script/basic/JDK-8062624.js.EXPECTED
new file mode 100644
index 00000000..2d6dea36
--- /dev/null
+++ b/test/script/basic/JDK-8062624.js.EXPECTED
@@ -0,0 +1,16 @@
+true
+false
+102
+102
+true
+false
+102,111,111
+102,111,111
+false
+false
+97,98,99
+97,98,99
+false
+true
+98,97,122,102,111,111,98,97,114
+98,97,122,102,111,111,98,97,114
diff --git a/test/script/basic/JDK-8062799.js b/test/script/basic/JDK-8062799.js
new file mode 100644
index 00000000..b3af6db4
--- /dev/null
+++ b/test/script/basic/JDK-8062799.js
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062799: Binary logical expressions can have numeric types
+ *
+ * @test
+ * @run
+ */
+
+(function() {
+ var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect;
+
+ var b = true;
+ var i = 1;
+ var l = 4294967296;
+ var d = 2.1;
+ var o = "foo";
+
+ print(inspect(b || b, "b || b"));
+ print(inspect(b || i, "b || i"));
+ print(inspect(b || l, "b || l"));
+ print(inspect(b || d, "b || d"));
+ print(inspect(b || o, "b || o"));
+
+ print(inspect(i || b, "i || b"));
+ print(inspect(i || i, "i || i"));
+ print(inspect(i || l, "i || l"));
+ print(inspect(i || d, "i || d"));
+ print(inspect(i || o, "i || o"));
+
+ print(inspect(l || b, "l || b"));
+ print(inspect(l || i, "l || i"));
+ print(inspect(l || l, "l || l"));
+ print(inspect(l || d, "l || d"));
+ print(inspect(l || o, "l || o"));
+
+ print(inspect(d || b, "d || b"));
+ print(inspect(d || i, "d || i"));
+ print(inspect(d || l, "d || l"));
+ print(inspect(d || d, "d || d"));
+ print(inspect(d || o, "d || o"));
+
+ print(inspect(o || b, "o || b"));
+ print(inspect(o || i, "o || i"));
+ print(inspect(o || l, "o || l"));
+ print(inspect(o || d, "o || d"));
+ print(inspect(o || o, "o || o"));
+
+ print(inspect(b && b, "b && b"));
+ print(inspect(b && i, "b && i"));
+ print(inspect(b && l, "b && l"));
+ print(inspect(b && d, "b && d"));
+ print(inspect(b && o, "b && o"));
+
+ print(inspect(i && b, "i && b"));
+ print(inspect(i && i, "i && i"));
+ print(inspect(i && l, "i && l"));
+ print(inspect(i && d, "i && d"));
+ print(inspect(i && o, "i && o"));
+
+ print(inspect(l && b, "l && b"));
+ print(inspect(l && i, "l && i"));
+ print(inspect(l && l, "l && l"));
+ print(inspect(l && d, "l && d"));
+ print(inspect(l && o, "l && o"));
+
+ print(inspect(d && b, "d && b"));
+ print(inspect(d && i, "d && i"));
+ print(inspect(d && l, "d && l"));
+ print(inspect(d && d, "d && d"));
+ print(inspect(d && o, "d && o"));
+
+ print(inspect(o && b, "o && b"));
+ print(inspect(o && i, "o && i"));
+ print(inspect(o && l, "o && l"));
+ print(inspect(o && d, "o && d"));
+ print(inspect(o && o, "o && o"));
+})();
+
+
+
+ \ No newline at end of file
diff --git a/test/script/basic/JDK-8062799.js.EXPECTED b/test/script/basic/JDK-8062799.js.EXPECTED
new file mode 100644
index 00000000..8fb88d82
--- /dev/null
+++ b/test/script/basic/JDK-8062799.js.EXPECTED
@@ -0,0 +1,50 @@
+b || b: boolean
+b || i: boolean
+b || l: boolean
+b || d: boolean
+b || o: boolean
+i || b: int
+i || i: int
+i || l: long
+i || d: double
+i || o: int
+l || b: long
+l || i: long
+l || l: long
+l || d: double
+l || o: long
+d || b: double
+d || i: double
+d || l: double
+d || d: double
+d || o: double
+o || b: object
+o || i: object
+o || l: object
+o || d: object
+o || o: object
+b && b: boolean
+b && i: int
+b && l: long
+b && d: double
+b && o: object
+i && b: boolean
+i && i: int
+i && l: long
+i && d: double
+i && o: object
+l && b: boolean
+l && i: long
+l && l: long
+l && d: double
+l && o: object
+d && b: boolean
+d && i: double
+d && l: double
+d && d: double
+d && o: object
+o && b: boolean
+o && i: int
+o && l: long
+o && d: double
+o && o: object
diff --git a/test/script/basic/JDK-8062937.js b/test/script/basic/JDK-8062937.js
new file mode 100644
index 00000000..d38161a7
--- /dev/null
+++ b/test/script/basic/JDK-8062937.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062937 - GlobalConstants produces wrong result with defineProperty and index setters
+ *
+ * @test
+ * @run
+ */
+
+var x = 1;
+for (var i = 2; i < 5; i++) {
+ print(x);
+ Object.defineProperty(this, "x", {value: i});
+}
+print(x);
+
+print();
+
+var name = "y";
+var y = 1;
+for (var i = 2; i < 5; i++) {
+ print(y);
+ this[name] = i;
+}
+print(y);
diff --git a/test/script/basic/JDK-8062937.js.EXPECTED b/test/script/basic/JDK-8062937.js.EXPECTED
new file mode 100644
index 00000000..4b6f9b6c
--- /dev/null
+++ b/test/script/basic/JDK-8062937.js.EXPECTED
@@ -0,0 +1,9 @@
+1
+2
+3
+4
+
+1
+2
+3
+4
diff --git a/test/script/basic/JDK-8066221.js b/test/script/basic/JDK-8066221.js
new file mode 100644
index 00000000..7af4dfa1
--- /dev/null
+++ b/test/script/basic/JDK-8066221.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066221: anonymous function statement name clashes with another symbol
+ * (compile-only test)
+ *
+ * @test
+ */
+
+x3 = function x1(x3) { function (){} };
diff --git a/test/script/basic/JDK-8066224.js b/test/script/basic/JDK-8066224.js
new file mode 100644
index 00000000..b29ba353
--- /dev/null
+++ b/test/script/basic/JDK-8066224.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066224: fixes for folding a constant-test ternary operator
+ *
+ * @test
+ * @run
+ */
+
+print((function(){
+ if(false ? 0 : '') {
+ throw false;
+ } else if (x = this) {
+ var x = x;
+ }
+ return x === this;
+})())
diff --git a/test/script/basic/JDK-8066224.js.EXPECTED b/test/script/basic/JDK-8066224.js.EXPECTED
new file mode 100644
index 00000000..27ba77dd
--- /dev/null
+++ b/test/script/basic/JDK-8066224.js.EXPECTED
@@ -0,0 +1 @@
+true
diff --git a/test/script/basic/JDK-8066225.js b/test/script/basic/JDK-8066225.js
new file mode 100644
index 00000000..84d56b81
--- /dev/null
+++ b/test/script/basic/JDK-8066225.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066225: NPE in MethodEmitter with duplicate integer switch cases
+ *
+ * @test
+ * @run
+ */
+
+(function (x){
+ switch(x) {
+ case 44: for (var x in {}) {x}; print("1");
+ case 44: print("2");
+ }
+})(44);
diff --git a/test/script/basic/JDK-8066225.js.EXPECTED b/test/script/basic/JDK-8066225.js.EXPECTED
new file mode 100644
index 00000000..1191247b
--- /dev/null
+++ b/test/script/basic/JDK-8066225.js.EXPECTED
@@ -0,0 +1,2 @@
+1
+2
diff --git a/test/script/basic/JDK-8066227.js b/test/script/basic/JDK-8066227.js
new file mode 100644
index 00000000..aded343f
--- /dev/null
+++ b/test/script/basic/JDK-8066227.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066227: CodeGenerator load unitialized slot
+ *
+ * @test
+ * @run
+ */
+
+print((function () { var x; (x += x = 0); return x; })());
+print((function () { var x; (x -= x = 0); return x; })());
+print((function () { var x; (x *= x = 0); return x; })());
+print((function () { var x; (x /= x = 0); return x; })());
+print((function () { var x; (x %= x = 0); return x; })());
+print((function () { var x; (x <<= x = 0); return x; })());
+print((function () { var x; (x >>= x = 0); return x; })());
+print((function () { var x; (x >>>= x = 0); return x; })());
+print((function () { var x; (x |= x = 0); return x; })());
+print((function () { var x; (x &= x = 0); return x; })());
diff --git a/test/script/basic/JDK-8066227.js.EXPECTED b/test/script/basic/JDK-8066227.js.EXPECTED
new file mode 100644
index 00000000..18418221
--- /dev/null
+++ b/test/script/basic/JDK-8066227.js.EXPECTED
@@ -0,0 +1,10 @@
+NaN
+NaN
+NaN
+NaN
+NaN
+0
+0
+0
+0
+0
diff --git a/test/script/basic/JDK-8066230.js b/test/script/basic/JDK-8066230.js
new file mode 100644
index 00000000..c6a3583f
--- /dev/null
+++ b/test/script/basic/JDK-8066230.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066230: Undefined object type assertion when computing TypeBounds
+ *
+ * @test
+ * @run
+ */
+
+(function() { void null + 0; })();
+(function() { var x; x += void x; })();
+(function() { var a = true + x, x; })();
+print("SUCCESS");
diff --git a/test/script/basic/JDK-8066230.js.EXPECTED b/test/script/basic/JDK-8066230.js.EXPECTED
new file mode 100644
index 00000000..ff43ca40
--- /dev/null
+++ b/test/script/basic/JDK-8066230.js.EXPECTED
@@ -0,0 +1 @@
+SUCCESS
diff --git a/test/script/basic/JDK-8066236.js b/test/script/basic/JDK-8066236.js
new file mode 100644
index 00000000..760e0f46
--- /dev/null
+++ b/test/script/basic/JDK-8066236.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066236: RuntimeNode forces copy creation on visitation
+ *
+ * @test
+ * @run
+ */
+
+// Note: we're using Function("code") instead of (function(){ code }) so that
+// we don't trigger parser API validation in JDK-8008448 tests. The test code
+// encapsulated in functions below can't be correctly handled by the parser API
+// currently, as it contains parser-generated REFERENCE_ERROR runtime nodes.
+try {
+ Function("L: {this = x;break L}")();
+} catch (e) {
+ print("threw ReferenceError: " + (e instanceof ReferenceError));
+}
+try {
+ Function("L:with(this--)break L;")();
+} catch (e) {
+ print("threw ReferenceError: " + (e instanceof ReferenceError));
+}
+Function("L:with(Object in Object)break L;")();
+print("SUCCESS");
diff --git a/test/script/basic/JDK-8066236.js.EXPECTED b/test/script/basic/JDK-8066236.js.EXPECTED
new file mode 100644
index 00000000..b64a3056
--- /dev/null
+++ b/test/script/basic/JDK-8066236.js.EXPECTED
@@ -0,0 +1,3 @@
+threw ReferenceError: true
+threw ReferenceError: true
+SUCCESS
diff --git a/test/script/basic/JDK-8066669.js b/test/script/basic/JDK-8066669.js
new file mode 100644
index 00000000..ea5a2860
--- /dev/null
+++ b/test/script/basic/JDK-8066669.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066669: dust.js performance regression caused by primitive field conversion
+ *
+ * @test
+ * @run
+ */
+
+// Make sure index access on Java objects is working as expected.
+var map = new java.util.HashMap();
+
+map["foo"] = "bar";
+map[1] = 2;
+map[false] = true;
+map[null] = 0;
+
+print(map);
+
+var keys = map.keySet().iterator();
+
+while(keys.hasNext()) {
+ var key = keys.next();
+ print(typeof key, key);
+}
+
+print(typeof map["foo"], map["foo"]);
+print(typeof map[1], map[1]);
+print(typeof map[false], map[false]);
+print(typeof map[null], map[null]);
+
+print(map.foo);
+print(map.false);
+print(map.null);
+
+map.foo = "baz";
+print(map);
diff --git a/test/script/basic/JDK-8066669.js.EXPECTED b/test/script/basic/JDK-8066669.js.EXPECTED
new file mode 100644
index 00000000..4af53817
--- /dev/null
+++ b/test/script/basic/JDK-8066669.js.EXPECTED
@@ -0,0 +1,13 @@
+{null=0, 1=2, false=true, foo=bar}
+object null
+number 1
+boolean false
+string foo
+string bar
+number 2
+boolean true
+number 0
+bar
+null
+null
+{null=0, 1=2, false=true, foo=baz}
diff --git a/test/script/basic/JDK-8066932.js b/test/script/basic/JDK-8066932.js
new file mode 100644
index 00000000..6dda1e09
--- /dev/null
+++ b/test/script/basic/JDK-8066932.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066932: __noSuchMethod__ binds to this-object without proper guard
+ *
+ * @test
+ * @run
+ */
+
+function C(id) {
+ this.id = id;
+}
+
+C.prototype.__noSuchMethod__ = function(name, args) {
+ return this.id;
+};
+
+function test(id) {
+ var c = new C(id);
+ return c.nonExistingMethod();
+}
+
+for (var i = 0; i < 30; i++) {
+ if (test(i) !== i) {
+ throw new Error("Wrong result from noSuchMethod in iteration " + i);
+ }
+}
diff --git a/test/script/basic/JDK-8067136.js b/test/script/basic/JDK-8067136.js
new file mode 100644
index 00000000..1c7c13a2
--- /dev/null
+++ b/test/script/basic/JDK-8067136.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8067136: BrowserJSObjectLinker does not handle call on JSObjects
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// call on netscape.javascript.JSObject
+
+function main() {
+ var JSObject;
+ try {
+ JSObject = Java.type("netscape.javascript.JSObject");
+ } catch (e) {
+ if (e instanceof java.lang.ClassNotFoundException) {
+ // pass vacuously by emitting the .EXPECTED file content
+ var str = readFully(__DIR__ + "JDK-8067136.js.EXPECTED");
+ print(str.substring(0, str.length - 1));
+ return;
+ } else{
+ fail("unexpected exception for JSObject", e);
+ }
+ }
+ test(JSObject);
+}
+
+function test(JSObject) {
+ var obj = new (Java.extend(JSObject))() {
+ getMember: function(name) {
+ if (name == "func") {
+ return new (Java.extend(JSObject)) {
+ call: function(n) {
+ print("func called");
+ }
+ }
+ }
+ return name.toUpperCase();
+ },
+
+ };
+
+ obj.func();
+}
+
+main();
diff --git a/test/script/basic/JDK-8067136.js.EXPECTED b/test/script/basic/JDK-8067136.js.EXPECTED
new file mode 100644
index 00000000..5897ee65
--- /dev/null
+++ b/test/script/basic/JDK-8067136.js.EXPECTED
@@ -0,0 +1 @@
+func called
diff --git a/test/script/basic/JDK_8005848.js b/test/script/basic/JDK_8005848.js
index d2d07eaf..6df67685 100644
--- a/test/script/basic/JDK_8005848.js
+++ b/test/script/basic/JDK_8005848.js
@@ -22,7 +22,7 @@
*/
/**
- * JDK-8005848 : assigning to global toString variable affects Object.prototype.toString
+ * JDK-8005848 : assigning to global toString variable affects Object.prototype.toString
*
* @test
* @run
diff --git a/test/script/basic/NASHORN-100.js b/test/script/basic/NASHORN-100.js
index df81284d..2b10a4db 100644
--- a/test/script/basic/NASHORN-100.js
+++ b/test/script/basic/NASHORN-100.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-101.js b/test/script/basic/NASHORN-101.js
index 4e83a99f..c9a551b7 100644
--- a/test/script/basic/NASHORN-101.js
+++ b/test/script/basic/NASHORN-101.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-102.js b/test/script/basic/NASHORN-102.js
index cc388dd9..25805b6c 100644
--- a/test/script/basic/NASHORN-102.js
+++ b/test/script/basic/NASHORN-102.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-103.js b/test/script/basic/NASHORN-103.js
index ddce5965..5c51130c 100644
--- a/test/script/basic/NASHORN-103.js
+++ b/test/script/basic/NASHORN-103.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-104.js b/test/script/basic/NASHORN-104.js
index c97b6bc6..13933885 100644
--- a/test/script/basic/NASHORN-104.js
+++ b/test/script/basic/NASHORN-104.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-105.js b/test/script/basic/NASHORN-105.js
index f26710d1..f6d1f147 100644
--- a/test/script/basic/NASHORN-105.js
+++ b/test/script/basic/NASHORN-105.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-105 : parseFloat function is not spec. compliant.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-106.js b/test/script/basic/NASHORN-106.js
index e5a9c612..585f1335 100644
--- a/test/script/basic/NASHORN-106.js
+++ b/test/script/basic/NASHORN-106.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-107.js b/test/script/basic/NASHORN-107.js
index 2aeb5dca..6bcbe1ac 100644
--- a/test/script/basic/NASHORN-107.js
+++ b/test/script/basic/NASHORN-107.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-108.js b/test/script/basic/NASHORN-108.js
index e12096bf..419d1e0d 100644
--- a/test/script/basic/NASHORN-108.js
+++ b/test/script/basic/NASHORN-108.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-109.js b/test/script/basic/NASHORN-109.js
index 4667feb2..bb6f08a3 100644
--- a/test/script/basic/NASHORN-109.js
+++ b/test/script/basic/NASHORN-109.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-11.js b/test/script/basic/NASHORN-11.js
index ca8565f8..5209b2af 100644
--- a/test/script/basic/NASHORN-11.js
+++ b/test/script/basic/NASHORN-11.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-111.js b/test/script/basic/NASHORN-111.js
index 4b8347c9..6b6d311d 100644
--- a/test/script/basic/NASHORN-111.js
+++ b/test/script/basic/NASHORN-111.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,7 +31,7 @@
try {
throw new TypeError("type error");
} catch (e) {
- // This used to throw ClassCastException
+ // This used to throw ClassCastException
// ThrowException cannot be cast to ScriptObject
print(JSON.stringify(e));
}
diff --git a/test/script/basic/NASHORN-113.js b/test/script/basic/NASHORN-113.js
index d90d1fb4..1421ed8e 100644
--- a/test/script/basic/NASHORN-113.js
+++ b/test/script/basic/NASHORN-113.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-114.js b/test/script/basic/NASHORN-114.js
index 03269214..e84cccf9 100644
--- a/test/script/basic/NASHORN-114.js
+++ b/test/script/basic/NASHORN-114.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-115.js b/test/script/basic/NASHORN-115.js
index 924a9a2b..18637167 100644
--- a/test/script/basic/NASHORN-115.js
+++ b/test/script/basic/NASHORN-115.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-117.js b/test/script/basic/NASHORN-117.js
index 9436150f..11aa3e4c 100644
--- a/test/script/basic/NASHORN-117.js
+++ b/test/script/basic/NASHORN-117.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-// The following code results in StackOverflowError
+// The following code results in StackOverflowError
var i0 = "";
var o0 = "";
diff --git a/test/script/basic/NASHORN-118.js b/test/script/basic/NASHORN-118.js
index d12d8614..641e80ec 100644
--- a/test/script/basic/NASHORN-118.js
+++ b/test/script/basic/NASHORN-118.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-118 : Function.prototype.apply should accept "arguments" object
+ * NASHORN-118 : Function.prototype.apply should accept "arguments" object
* of another function as second argument.
*
* @test
diff --git a/test/script/basic/NASHORN-119.js b/test/script/basic/NASHORN-119.js
index c957cdf2..e543600d 100644
--- a/test/script/basic/NASHORN-119.js
+++ b/test/script/basic/NASHORN-119.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-12.js b/test/script/basic/NASHORN-12.js
index ed04d621..95a9e594 100644
--- a/test/script/basic/NASHORN-12.js
+++ b/test/script/basic/NASHORN-12.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-120.js b/test/script/basic/NASHORN-120.js
index b424f3e0..2881bc09 100644
--- a/test/script/basic/NASHORN-120.js
+++ b/test/script/basic/NASHORN-120.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-122.js b/test/script/basic/NASHORN-122.js
index a8863a9b..08ad77bf 100644
--- a/test/script/basic/NASHORN-122.js
+++ b/test/script/basic/NASHORN-122.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-126.js b/test/script/basic/NASHORN-126.js
index dc3f3b33..bd2b6215 100644
--- a/test/script/basic/NASHORN-126.js
+++ b/test/script/basic/NASHORN-126.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,9 +26,9 @@
*
* @test
* @run
- */
+ */
print(String(1000000000000000000000) === "1e+21");
print(String(0.000000000100000000000) === "1e-10");
-
+
diff --git a/test/script/basic/NASHORN-127.js b/test/script/basic/NASHORN-127.js
index 3cd64d28..547b8e03 100644
--- a/test/script/basic/NASHORN-127.js
+++ b/test/script/basic/NASHORN-127.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,11 +29,11 @@
*/
try {
- try {
+ try {
throw ReferenceError(17);
- } catch (e) {
- print(e);
- throw TypeError(4711);
+ } catch (e) {
+ print(e);
+ throw TypeError(4711);
}
-} catch (e) { print(e);
+} catch (e) { print(e);
}
diff --git a/test/script/basic/NASHORN-130.js b/test/script/basic/NASHORN-130.js
index 64f275cd..3232794f 100644
--- a/test/script/basic/NASHORN-130.js
+++ b/test/script/basic/NASHORN-130.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-132.js b/test/script/basic/NASHORN-132.js
index f8ad281a..dcb167c5 100644
--- a/test/script/basic/NASHORN-132.js
+++ b/test/script/basic/NASHORN-132.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-133.js b/test/script/basic/NASHORN-133.js
index f4ddbe63..80d2e88e 100644
--- a/test/script/basic/NASHORN-133.js
+++ b/test/script/basic/NASHORN-133.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-135.js b/test/script/basic/NASHORN-135.js
index 6ffff06b..8f6fe3b0 100644
--- a/test/script/basic/NASHORN-135.js
+++ b/test/script/basic/NASHORN-135.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-136.js b/test/script/basic/NASHORN-136.js
index 473a3e1f..f896e4da 100644
--- a/test/script/basic/NASHORN-136.js
+++ b/test/script/basic/NASHORN-136.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@ var obj1 = {
valueOf: function() {
print("obj1.valueOf");
return 1;
- },
+ },
toString: function() {
print("obj1.toString");
diff --git a/test/script/basic/NASHORN-14.js b/test/script/basic/NASHORN-14.js
index 83a0a077..02ddc587 100644
--- a/test/script/basic/NASHORN-14.js
+++ b/test/script/basic/NASHORN-14.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
*/
-function callback() {
+function callback() {
print('callback with args ' + Array.prototype.join.apply(arguments))
}
diff --git a/test/script/basic/NASHORN-148.js b/test/script/basic/NASHORN-148.js
index 398b09d5..542ab64b 100644
--- a/test/script/basic/NASHORN-148.js
+++ b/test/script/basic/NASHORN-148.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,13 +23,13 @@
/**
* NASHORN-148 : arguments element deletion/resurrection does not work as expected
- *
+ *
* @test
* @run
*/
-function func(x) {
+function func(x) {
print("func.x = " + x);
print("func.arguments[0] = " + arguments[0]);
@@ -43,7 +43,7 @@ function func(x) {
print("func.arguments[0] = " + arguments[0]);
// delete arguments[0]
- delete arguments[0];
+ delete arguments[0];
print("func.x = " + x);
print("func.arguments[0] = " + arguments[0]);
diff --git a/test/script/basic/NASHORN-15.js b/test/script/basic/NASHORN-15.js
index 895fac6c..d8bdeb63 100644
--- a/test/script/basic/NASHORN-15.js
+++ b/test/script/basic/NASHORN-15.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-153.js b/test/script/basic/NASHORN-153.js
index e38c3e11..f375acd8 100644
--- a/test/script/basic/NASHORN-153.js
+++ b/test/script/basic/NASHORN-153.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-156.js b/test/script/basic/NASHORN-156.js
index 6a111e98..7cf19f24 100644
--- a/test/script/basic/NASHORN-156.js
+++ b/test/script/basic/NASHORN-156.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,8 +29,8 @@
* @run
*/
-var obj = {
- get foo() { return 3; }
+var obj = {
+ get foo() { return 3; }
};
if (obj.foo != 3) {
diff --git a/test/script/basic/NASHORN-157.js b/test/script/basic/NASHORN-157.js
index 1908d380..316b96c4 100644
--- a/test/script/basic/NASHORN-157.js
+++ b/test/script/basic/NASHORN-157.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-try {
+try {
print((x, 1));
fail("#1 ReferenceError should have been thrown");
} catch (e) {
diff --git a/test/script/basic/NASHORN-163.js b/test/script/basic/NASHORN-163.js
index d431a3de..92971718 100644
--- a/test/script/basic/NASHORN-163.js
+++ b/test/script/basic/NASHORN-163.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-163 : Object.keys(o) should only enumerate o's own properties
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-164.js b/test/script/basic/NASHORN-164.js
index f1b42eb8..2b24349f 100644
--- a/test/script/basic/NASHORN-164.js
+++ b/test/script/basic/NASHORN-164.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
var obj2 = { bar: 'hello' };
var obj = Object.create(obj2);
-obj.foo = 22;
+obj.foo = 22;
if (JSON.stringify(obj) != '{"foo":22}') {
throw Error("expected '{\"foo\":22}' got " + JSON.stringify(obj));
diff --git a/test/script/basic/NASHORN-165.js b/test/script/basic/NASHORN-165.js
index fc1008e4..5516b447 100644
--- a/test/script/basic/NASHORN-165.js
+++ b/test/script/basic/NASHORN-165.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-166.js b/test/script/basic/NASHORN-166.js
index 465f159b..95a960c5 100644
--- a/test/script/basic/NASHORN-166.js
+++ b/test/script/basic/NASHORN-166.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-168.js b/test/script/basic/NASHORN-168.js
index 138c3527..d9b5568a 100644
--- a/test/script/basic/NASHORN-168.js
+++ b/test/script/basic/NASHORN-168.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-169.js b/test/script/basic/NASHORN-169.js
index 4da52763..aacec29d 100644
--- a/test/script/basic/NASHORN-169.js
+++ b/test/script/basic/NASHORN-169.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-172.js b/test/script/basic/NASHORN-172.js
index 607642fc..26b6ed56 100644
--- a/test/script/basic/NASHORN-172.js
+++ b/test/script/basic/NASHORN-172.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,12 +28,12 @@
* @run
*/
-if (delete x !== true) {
+if (delete x !== true) {
fail('#1: delete x === true');
}
-if (delete this.x !== true) {
- fail('#2: delete this.x === true');
+if (delete this.x !== true) {
+ fail('#2: delete this.x === true');
}
var y = 23;
diff --git a/test/script/basic/NASHORN-173.js b/test/script/basic/NASHORN-173.js
index 1ee89f31..9e7a7c50 100644
--- a/test/script/basic/NASHORN-173.js
+++ b/test/script/basic/NASHORN-173.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-174.js b/test/script/basic/NASHORN-174.js
index e56c2583..7bc59ac8 100644
--- a/test/script/basic/NASHORN-174.js
+++ b/test/script/basic/NASHORN-174.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,7 +33,7 @@ var nums = "24.45.8.78".split('.');
if (nums.length != 4) {
fail("#1: split result expected to be of length 4");
}
-
+
function check(index, value) {
if (nums[index] != value) {
fail("expected value @ " + index + " is " + value);
diff --git a/test/script/basic/NASHORN-175.js b/test/script/basic/NASHORN-175.js
index be60d124..5ed5e06d 100644
--- a/test/script/basic/NASHORN-175.js
+++ b/test/script/basic/NASHORN-175.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-176.js b/test/script/basic/NASHORN-176.js
index 672362d4..fe1a696e 100644
--- a/test/script/basic/NASHORN-176.js
+++ b/test/script/basic/NASHORN-176.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-177.js b/test/script/basic/NASHORN-177.js
index 024a9d17..4815e13f 100644
--- a/test/script/basic/NASHORN-177.js
+++ b/test/script/basic/NASHORN-177.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-177 : null array elements become undefined on assignment
+ * NASHORN-177 : null array elements become undefined on assignment
*
* @test
* @run
diff --git a/test/script/basic/NASHORN-178.js b/test/script/basic/NASHORN-178.js
index 4e1a9190..70c0d66e 100644
--- a/test/script/basic/NASHORN-178.js
+++ b/test/script/basic/NASHORN-178.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-179.js b/test/script/basic/NASHORN-179.js
index d0b50ea8..c2b33a18 100644
--- a/test/script/basic/NASHORN-179.js
+++ b/test/script/basic/NASHORN-179.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-18.js b/test/script/basic/NASHORN-18.js
index 50115c9c..bc7f19ed 100644
--- a/test/script/basic/NASHORN-18.js
+++ b/test/script/basic/NASHORN-18.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-181.js b/test/script/basic/NASHORN-181.js
index 0ad8da51..7af652fc 100644
--- a/test/script/basic/NASHORN-181.js
+++ b/test/script/basic/NASHORN-181.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@ var props = { foo: { } };
try {
var obj = Object.create({}, props);
- if (! obj.hasOwnProperty("foo")) {
+ if (! obj.hasOwnProperty("foo")) {
fail("obj does not have 'foo' property");
}
} catch (e) {
diff --git a/test/script/basic/NASHORN-182.js b/test/script/basic/NASHORN-182.js
index 0e908dd4..278e3d9d 100644
--- a/test/script/basic/NASHORN-182.js
+++ b/test/script/basic/NASHORN-182.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
function callback(prev, cur, idx, obj) {
fail("callback with " + idx);
-}
+}
// array-like object
var obj = { 1: 1, 2: 2, length: 3 };
diff --git a/test/script/basic/NASHORN-183.js b/test/script/basic/NASHORN-183.js
index c90e7ba5..e64b2ea1 100644
--- a/test/script/basic/NASHORN-183.js
+++ b/test/script/basic/NASHORN-183.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-184.js b/test/script/basic/NASHORN-184.js
index d1524b9f..69ecaf20 100644
--- a/test/script/basic/NASHORN-184.js
+++ b/test/script/basic/NASHORN-184.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-185.js b/test/script/basic/NASHORN-185.js
index 508b5b30..c42eae3a 100644
--- a/test/script/basic/NASHORN-185.js
+++ b/test/script/basic/NASHORN-185.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-187.js b/test/script/basic/NASHORN-187.js
index 7238ecf7..d253464b 100644
--- a/test/script/basic/NASHORN-187.js
+++ b/test/script/basic/NASHORN-187.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,16 +31,16 @@
var obj = {};
try {
- Object.defineProperty(obj, "foo", {
- get: function() { return 22; },
- set: undefined
+ Object.defineProperty(obj, "foo", {
+ get: function() { return 22; },
+ set: undefined
});
} catch (e) {
fail("failed", e);
}
try {
- Object.defineProperty(obj, "bar", {
+ Object.defineProperty(obj, "bar", {
get: undefined
});
} catch (e) {
diff --git a/test/script/basic/NASHORN-188.js b/test/script/basic/NASHORN-188.js
index ce727139..baa02f3e 100644
--- a/test/script/basic/NASHORN-188.js
+++ b/test/script/basic/NASHORN-188.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-19.js b/test/script/basic/NASHORN-19.js
index 71a2db0d..88c6be01 100644
--- a/test/script/basic/NASHORN-19.js
+++ b/test/script/basic/NASHORN-19.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -38,8 +38,8 @@ var myscope = {
do {
with(myscope) {
- myvalue = 12;
- break;
+ myvalue = 12;
+ break;
}
} while (false);
@@ -62,15 +62,15 @@ var scope = {value:10};
var scope2 = {value:20};
while (true) {
with (scope) {
- print(value);
- value = 11;
- print(value);
- with (scope2) {
- print(value);
- value = 21;
- print(value);
- break;
- }
+ print(value);
+ value = 11;
+ print(value);
+ with (scope2) {
+ print(value);
+ value = 21;
+ print(value);
+ break;
+ }
}
}
@@ -83,19 +83,19 @@ function test1() {
var scope = {value:10};
var scope2 = {value:20};
while (true) {
- with (scope) {
- print(value);
- value = 11;
- print(value);
- with (scope2) {
- print(value);
- value = 21;
- print(value);
- break;
- }
- }
+ with (scope) {
+ print(value);
+ value = 11;
+ print(value);
+ with (scope2) {
+ print(value);
+ value = 21;
+ print(value);
+ break;
+ }
+ }
}
-
+
print(value);
}
@@ -104,14 +104,14 @@ function test2() {
var value = "hello";
var scope = {value:10};
while (true) {
- with (scope) {
- print(value);
- value = 11;
- print(value);
- if (value > ten()) {
- break;
- }
- }
+ with (scope) {
+ print(value);
+ value = 11;
+ print(value);
+ if (value > ten()) {
+ break;
+ }
+ }
}
print(value);
}
@@ -123,24 +123,24 @@ function test3() {
var scope2 = {value:20};
var outer = 0;
while (outer < 5) {
- var i=0;
- while (i < 10) {
- with(scope) {
- print("loop header "+i);
- with (scope2) {
- value = 11;
- i++;
- if ((i & 1) != 0) {
- print("continue");
- continue;
- }
- }
- }
- print(value);
- }
- outer++;
+ var i=0;
+ while (i < 10) {
+ with(scope) {
+ print("loop header "+i);
+ with (scope2) {
+ value = 11;
+ i++;
+ if ((i & 1) != 0) {
+ print("continue");
+ continue;
+ }
+ }
+ }
+ print(value);
}
-}
+ outer++;
+ }
+}
//continue one level
function test4() {
@@ -148,15 +148,15 @@ function test4() {
var scope = {value:10};
var i=0;
while (i < 10) {
- print("loop header "+i);
- with (scope) {
- value = 11;
- i++;
- if ((i & 1) != 0) {
- print("continue");
- continue;
- }
- }
+ print("loop header "+i);
+ with (scope) {
+ value = 11;
+ i++;
+ if ((i & 1) != 0) {
+ print("continue");
+ continue;
+ }
+ }
}
print(value);
}
@@ -170,24 +170,24 @@ function test5() {
var outer = 0;
outer_label:
while (outer < 5) {
- var i=0;
- while (i < 10) {
- with(scope) {
- print("loop header "+i);
- with (scope2) {
- value = 11;
- i++;
- if ((i & 1) != 0) {
- print("continue");
- outer++;
- continue outer_label;
- }
- }
- }
- print(value);
- }
+ var i=0;
+ while (i < 10) {
+ with(scope) {
+ print("loop header "+i);
+ with (scope2) {
+ value = 11;
+ i++;
+ if ((i & 1) != 0) {
+ print("continue");
+ outer++;
+ continue outer_label;
+ }
+ }
+ }
+ print(value);
+ }
}
-}
+}
//labelled break
function test6() {
@@ -196,21 +196,21 @@ function test6() {
var scope2 = {value:20};
outer:
{
- var i=0;
- while (i < 10) {
- with(scope) {
- print("loop header "+i);
- with (scope2) {
- value = 11;
- i++;
- if ((i & 1) != 0) {
- print("break");
- break outer;
- }
- }
- }
- print(value);
- }
+ var i=0;
+ while (i < 10) {
+ with(scope) {
+ print("loop header "+i);
+ with (scope2) {
+ value = 11;
+ i++;
+ if ((i & 1) != 0) {
+ print("break");
+ break outer;
+ }
+ }
+ }
+ print(value);
+ }
}
}
@@ -218,32 +218,32 @@ function test6() {
function test7() {
var value = "hello";
var scope = {value:10};
- var scope2 = {value:20};
+ var scope2 = {value:20};
var global = false;
try {
- with(scope) {
- try {
- print(value);
- value = 4711;
- print(value);
- with(scope2) {
- print(value);
- value = 17;
- print(value);
- global = true;
- throw "inner";
- }
- } catch (ei) {
- print(ei);
- print(value);
- if (global) {
- throw "outer";
- }
- }
- }
+ with(scope) {
+ try {
+ print(value);
+ value = 4711;
+ print(value);
+ with(scope2) {
+ print(value);
+ value = 17;
+ print(value);
+ global = true;
+ throw "inner";
+ }
+ } catch (ei) {
+ print(ei);
+ print(value);
+ if (global) {
+ throw "outer";
+ }
+ }
+ }
} catch (eo) {
- print(eo);
- print(value);
+ print(eo);
+ print(value);
}
print(value);
}
diff --git a/test/script/basic/NASHORN-190.js b/test/script/basic/NASHORN-190.js
index 06e51a3c..919de571 100644
--- a/test/script/basic/NASHORN-190.js
+++ b/test/script/basic/NASHORN-190.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-var obj = {
+var obj = {
20: 'world', "2.3": 'hello'
};
diff --git a/test/script/basic/NASHORN-192.js b/test/script/basic/NASHORN-192.js
index 8fdc82b6..9cd55e70 100644
--- a/test/script/basic/NASHORN-192.js
+++ b/test/script/basic/NASHORN-192.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-192 : User defined property setter or getter with extra arguments or lesser argument fails by throwing exception
- *
+ *
* @test
* @run
*/
@@ -59,7 +59,7 @@ Object.defineProperty(obj, "prop", {
set: function(obj1, obj2, obj3) {
this.val = obj1;
}
-});
+});
try {
obj.prop = 33;
diff --git a/test/script/basic/NASHORN-194.js b/test/script/basic/NASHORN-194.js
index bbbc1945..21bb00d8 100644
--- a/test/script/basic/NASHORN-194.js
+++ b/test/script/basic/NASHORN-194.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-196.js b/test/script/basic/NASHORN-196.js
index 071da970..562e623f 100644
--- a/test/script/basic/NASHORN-196.js
+++ b/test/script/basic/NASHORN-196.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,7 +33,7 @@ var arr = [0, 1];
Object.defineProperty(arr, "length", {
value: -0
});
-
+
if (arr.length !== 0) {
fail("array length is not zero!");
}
diff --git a/test/script/basic/NASHORN-198.js b/test/script/basic/NASHORN-198.js
index ea99a3be..f0b73394 100644
--- a/test/script/basic/NASHORN-198.js
+++ b/test/script/basic/NASHORN-198.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-20.js b/test/script/basic/NASHORN-20.js
index b0d6cc90..7558f2bd 100644
--- a/test/script/basic/NASHORN-20.js
+++ b/test/script/basic/NASHORN-20.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-201.js b/test/script/basic/NASHORN-201.js
index 11bcf272..9631140d 100644
--- a/test/script/basic/NASHORN-201.js
+++ b/test/script/basic/NASHORN-201.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-202.js b/test/script/basic/NASHORN-202.js
index 53c7fb12..24c218dc 100644
--- a/test/script/basic/NASHORN-202.js
+++ b/test/script/basic/NASHORN-202.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-203.js b/test/script/basic/NASHORN-203.js
index 94acb3e1..aa15d3a3 100644
--- a/test/script/basic/NASHORN-203.js
+++ b/test/script/basic/NASHORN-203.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-204.js b/test/script/basic/NASHORN-204.js
index 98dedbaa..ce8be381 100644
--- a/test/script/basic/NASHORN-204.js
+++ b/test/script/basic/NASHORN-204.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-205.js b/test/script/basic/NASHORN-205.js
index 15bb3894..caf05e9c 100644
--- a/test/script/basic/NASHORN-205.js
+++ b/test/script/basic/NASHORN-205.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -54,7 +54,7 @@ try {
} catch (e) {
fail("failed", e);
}
-
+
var newDesc = Object.getOwnPropertyDescriptor(obj, "foo");
if (! newDesc.hasOwnProperty("value")) {
fail("'value' missing!!");
diff --git a/test/script/basic/NASHORN-206.js b/test/script/basic/NASHORN-206.js
index 537a9903..df346394 100644
--- a/test/script/basic/NASHORN-206.js
+++ b/test/script/basic/NASHORN-206.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-207.js b/test/script/basic/NASHORN-207.js
index b337ce3f..5950b94b 100644
--- a/test/script/basic/NASHORN-207.js
+++ b/test/script/basic/NASHORN-207.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,7 +37,7 @@ try {
} catch (e) {
if (! (e instanceof SyntaxError)) {
fail("#2 SyntaxError expected but got " + e);
- }
+ }
}
// cannot delete function parameter variable
@@ -47,7 +47,7 @@ try {
} catch(e) {
if (! (e instanceof SyntaxError)) {
fail("#4 SyntaxError expected but got " + e);
- }
+ }
}
// assignment can't be used to define as new variable
diff --git a/test/script/basic/NASHORN-207_2.js b/test/script/basic/NASHORN-207_2.js
index 681a3c28..76704e06 100644
--- a/test/script/basic/NASHORN-207_2.js
+++ b/test/script/basic/NASHORN-207_2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-208.js b/test/script/basic/NASHORN-208.js
index f7b28613..360d0e85 100644
--- a/test/script/basic/NASHORN-208.js
+++ b/test/script/basic/NASHORN-208.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-208
+ * NASHORN-208
*
* @test
* @run
diff --git a/test/script/basic/NASHORN-209.js b/test/script/basic/NASHORN-209.js
index 9fa781ce..c3319cfe 100644
--- a/test/script/basic/NASHORN-209.js
+++ b/test/script/basic/NASHORN-209.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,8 +28,8 @@
* @run
*/
-var obj = {
- in: 11, class: 'hello', try: false,
+var obj = {
+ in: 11, class: 'hello', try: false,
typeof: 456, instanceof: 'world',
catch: function() { print("catch called"); }
};
diff --git a/test/script/basic/NASHORN-21.js b/test/script/basic/NASHORN-21.js
index 14db4dc5..dbae299e 100644
--- a/test/script/basic/NASHORN-21.js
+++ b/test/script/basic/NASHORN-21.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-211.js b/test/script/basic/NASHORN-211.js
index 681caad9..5b22452e 100644
--- a/test/script/basic/NASHORN-211.js
+++ b/test/script/basic/NASHORN-211.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-212.js b/test/script/basic/NASHORN-212.js
index 681c7756..0a74e0df 100644
--- a/test/script/basic/NASHORN-212.js
+++ b/test/script/basic/NASHORN-212.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-213.js b/test/script/basic/NASHORN-213.js
index 03a37d9f..366d3185 100644
--- a/test/script/basic/NASHORN-213.js
+++ b/test/script/basic/NASHORN-213.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-215.js b/test/script/basic/NASHORN-215.js
index 53ff42e1..8d144841 100644
--- a/test/script/basic/NASHORN-215.js
+++ b/test/script/basic/NASHORN-215.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-216.js b/test/script/basic/NASHORN-216.js
index e9b1aee6..8e50b231 100644
--- a/test/script/basic/NASHORN-216.js
+++ b/test/script/basic/NASHORN-216.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-217.js b/test/script/basic/NASHORN-217.js
index 3885c70d..97cde448 100644
--- a/test/script/basic/NASHORN-217.js
+++ b/test/script/basic/NASHORN-217.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-219.js b/test/script/basic/NASHORN-219.js
index b7da209b..bb3b25e2 100644
--- a/test/script/basic/NASHORN-219.js
+++ b/test/script/basic/NASHORN-219.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-22.js b/test/script/basic/NASHORN-22.js
index 89f677ca..e96be955 100644
--- a/test/script/basic/NASHORN-22.js
+++ b/test/script/basic/NASHORN-22.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-221.js b/test/script/basic/NASHORN-221.js
index 87132bce..e743cec8 100644
--- a/test/script/basic/NASHORN-221.js
+++ b/test/script/basic/NASHORN-221.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-222.js b/test/script/basic/NASHORN-222.js
index a5a61f07..c1809b9d 100644
--- a/test/script/basic/NASHORN-222.js
+++ b/test/script/basic/NASHORN-222.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-223.js b/test/script/basic/NASHORN-223.js
index dd862d5d..f5baa977 100644
--- a/test/script/basic/NASHORN-223.js
+++ b/test/script/basic/NASHORN-223.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-225.js b/test/script/basic/NASHORN-225.js
index c7744c34..bc2e1d54 100644
--- a/test/script/basic/NASHORN-225.js
+++ b/test/script/basic/NASHORN-225.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-226.js b/test/script/basic/NASHORN-226.js
index 521c3a6d..6ea30f9b 100644
--- a/test/script/basic/NASHORN-226.js
+++ b/test/script/basic/NASHORN-226.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-227.js b/test/script/basic/NASHORN-227.js
index 787bdfa3..bb2b0fe7 100644
--- a/test/script/basic/NASHORN-227.js
+++ b/test/script/basic/NASHORN-227.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-228.js b/test/script/basic/NASHORN-228.js
index bb3bd8b5..26ce8326 100644
--- a/test/script/basic/NASHORN-228.js
+++ b/test/script/basic/NASHORN-228.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -51,4 +51,4 @@ for (i in x) {
fail("typeof key of a string is not 'string'");
}
}
-
+
diff --git a/test/script/basic/NASHORN-229.js b/test/script/basic/NASHORN-229.js
index fefc3188..63bcdd6d 100644
--- a/test/script/basic/NASHORN-229.js
+++ b/test/script/basic/NASHORN-229.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -39,4 +39,4 @@ if (! func1()) {
}
load(__DIR__ + 'NASHORN-229_subtest.js');
-
+
diff --git a/test/script/basic/NASHORN-229_subtest.js b/test/script/basic/NASHORN-229_subtest.js
index a722a98b..f3854471 100644
--- a/test/script/basic/NASHORN-229_subtest.js
+++ b/test/script/basic/NASHORN-229_subtest.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
function func2() {
var obj2 = {
get bar() { return 343; }
- };
+ };
return (obj2.bar === 343);
}
diff --git a/test/script/basic/NASHORN-23.js b/test/script/basic/NASHORN-23.js
index eab229e6..98f0a46f 100644
--- a/test/script/basic/NASHORN-23.js
+++ b/test/script/basic/NASHORN-23.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-23: calling function valued global variable before it is initialized should fail.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-232.js b/test/script/basic/NASHORN-232.js
index a2033bac..d977dc5f 100644
--- a/test/script/basic/NASHORN-232.js
+++ b/test/script/basic/NASHORN-232.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-234.js b/test/script/basic/NASHORN-234.js
index 87fec55c..7c5bd2db 100644
--- a/test/script/basic/NASHORN-234.js
+++ b/test/script/basic/NASHORN-234.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-235.js b/test/script/basic/NASHORN-235.js
index f01d3f46..98fe94c2 100644
--- a/test/script/basic/NASHORN-235.js
+++ b/test/script/basic/NASHORN-235.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-236.js b/test/script/basic/NASHORN-236.js
index 5fdb7f88..b4082eb4 100644
--- a/test/script/basic/NASHORN-236.js
+++ b/test/script/basic/NASHORN-236.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-237.js b/test/script/basic/NASHORN-237.js
index 37b07b34..23559f4b 100644
--- a/test/script/basic/NASHORN-237.js
+++ b/test/script/basic/NASHORN-237.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-239.js b/test/script/basic/NASHORN-239.js
index ca94bccb..918049a9 100644
--- a/test/script/basic/NASHORN-239.js
+++ b/test/script/basic/NASHORN-239.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-24.js b/test/script/basic/NASHORN-24.js
index 9f4f66d1..e612d21d 100644
--- a/test/script/basic/NASHORN-24.js
+++ b/test/script/basic/NASHORN-24.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-24: function local var assignments should resolve to 'with' scope if found in scope.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-241.js b/test/script/basic/NASHORN-241.js
index 7d887a62..1fb3e9ae 100644
--- a/test/script/basic/NASHORN-241.js
+++ b/test/script/basic/NASHORN-241.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
try {
new 1;
- fail('new "1" should have thrown TypeError');
+ fail('new "1" should have thrown TypeError');
} catch (e) {
if (! (e instanceof TypeError)) {
fail('expected TypeError, got ' + e, e);
@@ -40,7 +40,7 @@ try {
try {
var x = "1";
new x;
- fail('var x = "1"; new x should have thrown TypeError');
+ fail('var x = "1"; new x should have thrown TypeError');
} catch (e) {
if (! (e instanceof TypeError)) {
fail('var x = "1"; new x - expected TypeError, got ' + e, e);
@@ -50,10 +50,10 @@ try {
try {
var x = "1";
new x();
- fail('var x = "1"; new x() should have thrown TypeError');
+ fail('var x = "1"; new x() should have thrown TypeError');
} catch (e) {
if (! (e instanceof TypeError)) {
- fail('var x = "1"; new x() - expected TypeError, got ' + e);
+ fail('var x = "1"; new x() - expected TypeError, got ' + e);
}
}
diff --git a/test/script/basic/NASHORN-242.js b/test/script/basic/NASHORN-242.js
index 3e362bc2..edbc3bb7 100644
--- a/test/script/basic/NASHORN-242.js
+++ b/test/script/basic/NASHORN-242.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-245.js b/test/script/basic/NASHORN-245.js
index ced3e39c..3c43b92b 100644
--- a/test/script/basic/NASHORN-245.js
+++ b/test/script/basic/NASHORN-245.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-247.js b/test/script/basic/NASHORN-247.js
index b05db7ea..1187c0c7 100644
--- a/test/script/basic/NASHORN-247.js
+++ b/test/script/basic/NASHORN-247.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-25.js b/test/script/basic/NASHORN-25.js
index 0d40ffe1..d1bacaae 100644
--- a/test/script/basic/NASHORN-25.js
+++ b/test/script/basic/NASHORN-25.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-251.js b/test/script/basic/NASHORN-251.js
index bc5147f1..abe6c1cf 100644
--- a/test/script/basic/NASHORN-251.js
+++ b/test/script/basic/NASHORN-251.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-252.js b/test/script/basic/NASHORN-252.js
index 5e0a652f..7b59d979 100644
--- a/test/script/basic/NASHORN-252.js
+++ b/test/script/basic/NASHORN-252.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-253.js b/test/script/basic/NASHORN-253.js
index f562c97f..518344e4 100644
--- a/test/script/basic/NASHORN-253.js
+++ b/test/script/basic/NASHORN-253.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-256.js b/test/script/basic/NASHORN-256.js
index 1885873d..47bf128a 100644
--- a/test/script/basic/NASHORN-256.js
+++ b/test/script/basic/NASHORN-256.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-258.js b/test/script/basic/NASHORN-258.js
index 6d71266a..c3f614fe 100644
--- a/test/script/basic/NASHORN-258.js
+++ b/test/script/basic/NASHORN-258.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,28 +30,28 @@
function test3(a) {
for (i = 0; i < a.length ; i++) {
- for (j = 0; j < a[i].length ; j++) {
- for (k = 0; k < a[i][j].length ; k++) {
- a[i][j][k] *= 8;
- }
- }
+ for (j = 0; j < a[i].length ; j++) {
+ for (k = 0; k < a[i][j].length ; k++) {
+ a[i][j][k] *= 8;
+ }
+ }
}
}
function test3local(a) {
for (var i = 0; i < a.length ; i++) {
- for (var j = 0; j < a[i].length ; j++) {
- for (var k = 0; k < a[i][j].length ; k++) {
- a[i][j][k] *= 8;
- }
- }
+ for (var j = 0; j < a[i].length ; j++) {
+ for (var k = 0; k < a[i][j].length ; k++) {
+ a[i][j][k] *= 8;
+ }
+ }
}
}
var array = [ [[1,1,1],[1,1,1],[1,1,1]],
- [[1,1,1],[1,1,1],[1,1,1]],
- [[1,1,1],[1,1,1],[1,1,1]] ];
-
+ [[1,1,1],[1,1,1],[1,1,1]],
+ [[1,1,1],[1,1,1],[1,1,1]] ];
+
test3(array);
print(array);
@@ -59,17 +59,17 @@ test3local(array);
print(array);
function outer() {
-
+
var array2 = [ [[1,1,1],[1,1,1],[1,1,1]],
- [[1,1,1],[1,1,1],[1,1,1]],
- [[1,1,1],[1,1,1],[1,1,1]] ];
-
+ [[1,1,1],[1,1,1],[1,1,1]],
+ [[1,1,1],[1,1,1],[1,1,1]] ];
+
var f = function inner() {
- for (var i = 0; i < array2.length ; i++) {
- for (var j = 0; j < array2[i].length ; j++) {
- array2[i][j][2] *= 8;
- }
- }
+ for (var i = 0; i < array2.length ; i++) {
+ for (var j = 0; j < array2[i].length ; j++) {
+ array2[i][j][2] *= 8;
+ }
+ }
};
f();
diff --git a/test/script/basic/NASHORN-26.js b/test/script/basic/NASHORN-26.js
index d4525a36..e6bb65e8 100644
--- a/test/script/basic/NASHORN-26.js
+++ b/test/script/basic/NASHORN-26.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-260.js b/test/script/basic/NASHORN-260.js
index d1f1fcc5..172fc1e1 100644
--- a/test/script/basic/NASHORN-260.js
+++ b/test/script/basic/NASHORN-260.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-261.js b/test/script/basic/NASHORN-261.js
index c53facfe..4bab60b9 100644
--- a/test/script/basic/NASHORN-261.js
+++ b/test/script/basic/NASHORN-261.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -75,7 +75,7 @@ eval = function() {
}
}
-// pass no args to our overwritten eval
+// pass no args to our overwritten eval
// the new eval should not print anything (no hidden args passed)
eval();
diff --git a/test/script/basic/NASHORN-262.js b/test/script/basic/NASHORN-262.js
index 42eba1c7..8e0adad0 100644
--- a/test/script/basic/NASHORN-262.js
+++ b/test/script/basic/NASHORN-262.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-262 : for statement iterator variable is not checked in strict mode
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-263.js b/test/script/basic/NASHORN-263.js
index 62ce47bf..2ee2221f 100644
--- a/test/script/basic/NASHORN-263.js
+++ b/test/script/basic/NASHORN-263.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-264.js b/test/script/basic/NASHORN-264.js
index 88cd2b3e..4e196000 100644
--- a/test/script/basic/NASHORN-264.js
+++ b/test/script/basic/NASHORN-264.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-265.js b/test/script/basic/NASHORN-265.js
index 88344f59..52371ced 100644
--- a/test/script/basic/NASHORN-265.js
+++ b/test/script/basic/NASHORN-265.js
@@ -1,27 +1,27 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-/**
+/**
* NASHORN-265 with scope access within a nested function can't access global var
*
* @test
diff --git a/test/script/basic/NASHORN-266.js b/test/script/basic/NASHORN-266.js
index bfc600f9..a612558b 100644
--- a/test/script/basic/NASHORN-266.js
+++ b/test/script/basic/NASHORN-266.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-269.js b/test/script/basic/NASHORN-269.js
index 92feb76a..113e89d0 100644
--- a/test/script/basic/NASHORN-269.js
+++ b/test/script/basic/NASHORN-269.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-27.js b/test/script/basic/NASHORN-27.js
index b949b340..0253f1a0 100644
--- a/test/script/basic/NASHORN-27.js
+++ b/test/script/basic/NASHORN-27.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-270.js b/test/script/basic/NASHORN-270.js
index 89ef0d80..8fd01e5c 100644
--- a/test/script/basic/NASHORN-270.js
+++ b/test/script/basic/NASHORN-270.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-271.js b/test/script/basic/NASHORN-271.js
index 75c480df..def14fe3 100644
--- a/test/script/basic/NASHORN-271.js
+++ b/test/script/basic/NASHORN-271.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-var res = JSON.stringify(23, function(k,v) {
+var res = JSON.stringify(23, function(k,v) {
return (v == 23)? [1, 2] : v;
});
@@ -36,8 +36,8 @@ if (res !== "[1,2]") {
fail("#1 expected '[1,2]' got " + res);
}
-var res = JSON.stringify(23, function(k,v) {
- return (v == 23)? { x: 1, y: 'hello' } : v;
+var res = JSON.stringify(23, function(k,v) {
+ return (v == 23)? { x: 1, y: 'hello' } : v;
});
if (res !== '{"x":1,"y":"hello"}') {
diff --git a/test/script/basic/NASHORN-275.js b/test/script/basic/NASHORN-275.js
index 46c88fe0..90fe3994 100644
--- a/test/script/basic/NASHORN-275.js
+++ b/test/script/basic/NASHORN-275.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-276.js b/test/script/basic/NASHORN-276.js
index 3bce88f0..95a190f5 100644
--- a/test/script/basic/NASHORN-276.js
+++ b/test/script/basic/NASHORN-276.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-277.js b/test/script/basic/NASHORN-277.js
index 38724b30..f05aed08 100644
--- a/test/script/basic/NASHORN-277.js
+++ b/test/script/basic/NASHORN-277.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-278.js b/test/script/basic/NASHORN-278.js
index c8bf46ed..6196de47 100644
--- a/test/script/basic/NASHORN-278.js
+++ b/test/script/basic/NASHORN-278.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-28.js b/test/script/basic/NASHORN-28.js
index dc964c38..c3dc1029 100644
--- a/test/script/basic/NASHORN-28.js
+++ b/test/script/basic/NASHORN-28.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-281.js b/test/script/basic/NASHORN-281.js
index 77abe810..e70288bd 100644
--- a/test/script/basic/NASHORN-281.js
+++ b/test/script/basic/NASHORN-281.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-284.js b/test/script/basic/NASHORN-284.js
index 41f210ee..3768e41c 100644
--- a/test/script/basic/NASHORN-284.js
+++ b/test/script/basic/NASHORN-284.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-285.js b/test/script/basic/NASHORN-285.js
index a7d586e6..4401766d 100644
--- a/test/script/basic/NASHORN-285.js
+++ b/test/script/basic/NASHORN-285.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,31 +28,31 @@
* @run
*/
-function do_not_loop_forever() {
+function do_not_loop_forever() {
var sum = 0;
- for (var i = 0; i < 4711; i++) {
- sum += i;
- if (i >= 0) {
- continue;
- }
- return sum;
- }
+ for (var i = 0; i < 4711; i++) {
+ sum += i;
+ if (i >= 0) {
+ continue;
+ }
+ return sum;
+ }
return sum;
}
function still_tag_terminal() {
var sum = 0;
- for (var i = 0; i < 4711; i++) {
- sum += i;
- for (var j = 0; j < 4712; j++) {
- sum += j;
- if (j & 1) {
- continue;
- }
- }
- return sum;
- }
+ for (var i = 0; i < 4711; i++) {
+ sum += i;
+ for (var j = 0; j < 4712; j++) {
+ sum += j;
+ if (j & 1) {
+ continue;
+ }
+ }
+ return sum;
+ }
return sum;
}
diff --git a/test/script/basic/NASHORN-288.js b/test/script/basic/NASHORN-288.js
index b0c43a92..175db500 100644
--- a/test/script/basic/NASHORN-288.js
+++ b/test/script/basic/NASHORN-288.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-29.js b/test/script/basic/NASHORN-29.js
index 2455fa96..5cc85478 100644
--- a/test/script/basic/NASHORN-29.js
+++ b/test/script/basic/NASHORN-29.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-293.js b/test/script/basic/NASHORN-293.js
index 013714b8..016215ff 100644
--- a/test/script/basic/NASHORN-293.js
+++ b/test/script/basic/NASHORN-293.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-294.js b/test/script/basic/NASHORN-294.js
index 5de3f906..b2f6e52e 100644
--- a/test/script/basic/NASHORN-294.js
+++ b/test/script/basic/NASHORN-294.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-296.js b/test/script/basic/NASHORN-296.js
index 26338e60..dfc1ab99 100644
--- a/test/script/basic/NASHORN-296.js
+++ b/test/script/basic/NASHORN-296.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-297.js b/test/script/basic/NASHORN-297.js
index 5486a132..1915646b 100644
--- a/test/script/basic/NASHORN-297.js
+++ b/test/script/basic/NASHORN-297.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-30.js b/test/script/basic/NASHORN-30.js
index 95676cf3..fb68c73c 100644
--- a/test/script/basic/NASHORN-30.js
+++ b/test/script/basic/NASHORN-30.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,11 +30,11 @@
var obj = {
valueOf: function() {
- print("valueOf call");
- return -2
+ print("valueOf call");
+ return -2
},
- toString: function() {
+ toString: function() {
print("toString call");
return "-2";
}
diff --git a/test/script/basic/NASHORN-300.js b/test/script/basic/NASHORN-300.js
index fce230a2..0d8f1ba0 100644
--- a/test/script/basic/NASHORN-300.js
+++ b/test/script/basic/NASHORN-300.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,9 +29,9 @@
*/
function func1(foo) {
- if (foo) {
+ if (foo) {
var encoding = arguments[3];
- }
+ }
var s = encoding;
}
diff --git a/test/script/basic/NASHORN-301.js b/test/script/basic/NASHORN-301.js
index b00b78dd..9625273f 100644
--- a/test/script/basic/NASHORN-301.js
+++ b/test/script/basic/NASHORN-301.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-304.js b/test/script/basic/NASHORN-304.js
index 4d740e09..fac3be0b 100644
--- a/test/script/basic/NASHORN-304.js
+++ b/test/script/basic/NASHORN-304.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-310.js b/test/script/basic/NASHORN-310.js
index c49c2b4e..9b5c94e6 100644
--- a/test/script/basic/NASHORN-310.js
+++ b/test/script/basic/NASHORN-310.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-318.js b/test/script/basic/NASHORN-318.js
index 209a6bd4..16bbe5a3 100644
--- a/test/script/basic/NASHORN-318.js
+++ b/test/script/basic/NASHORN-318.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-32.js b/test/script/basic/NASHORN-32.js
index 0fd625b6..7b958f61 100644
--- a/test/script/basic/NASHORN-32.js
+++ b/test/script/basic/NASHORN-32.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-321.js b/test/script/basic/NASHORN-321.js
index 9510c175..56b427a9 100644
--- a/test/script/basic/NASHORN-321.js
+++ b/test/script/basic/NASHORN-321.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-323.js b/test/script/basic/NASHORN-323.js
index c1715c0f..f3e344e8 100644
--- a/test/script/basic/NASHORN-323.js
+++ b/test/script/basic/NASHORN-323.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-324.js b/test/script/basic/NASHORN-324.js
index 11aa51cc..929c9f37 100644
--- a/test/script/basic/NASHORN-324.js
+++ b/test/script/basic/NASHORN-324.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-33.js b/test/script/basic/NASHORN-33.js
index 2ed87e4a..af77f21f 100644
--- a/test/script/basic/NASHORN-33.js
+++ b/test/script/basic/NASHORN-33.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-331.js b/test/script/basic/NASHORN-331.js
index 41ce5294..46b61b6c 100644
--- a/test/script/basic/NASHORN-331.js
+++ b/test/script/basic/NASHORN-331.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-331 : Nan compares
+ * NASHORN-331 : Nan compares
*
* @test
* @run
diff --git a/test/script/basic/NASHORN-337.js b/test/script/basic/NASHORN-337.js
index dc8bac1d..9361eb9c 100644
--- a/test/script/basic/NASHORN-337.js
+++ b/test/script/basic/NASHORN-337.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-337 - Erroneous DCMPL/DCMPG instructions were generated
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-34.js b/test/script/basic/NASHORN-34.js
index 267768df..c835a3d2 100644
--- a/test/script/basic/NASHORN-34.js
+++ b/test/script/basic/NASHORN-34.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-340.js b/test/script/basic/NASHORN-340.js
index c20ceabf..a458e08a 100644
--- a/test/script/basic/NASHORN-340.js
+++ b/test/script/basic/NASHORN-340.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-349.js b/test/script/basic/NASHORN-349.js
index a611a589..bf17f3e4 100644
--- a/test/script/basic/NASHORN-349.js
+++ b/test/script/basic/NASHORN-349.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-354.js b/test/script/basic/NASHORN-354.js
index 506a0324..f0198857 100644
--- a/test/script/basic/NASHORN-354.js
+++ b/test/script/basic/NASHORN-354.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-355.js b/test/script/basic/NASHORN-355.js
index f0360726..0dc17cb6 100644
--- a/test/script/basic/NASHORN-355.js
+++ b/test/script/basic/NASHORN-355.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-36.js b/test/script/basic/NASHORN-36.js
index 3a8a0c97..4c93c682 100644
--- a/test/script/basic/NASHORN-36.js
+++ b/test/script/basic/NASHORN-36.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-365.js b/test/script/basic/NASHORN-365.js
index fe79e8c3..74018f26 100644
--- a/test/script/basic/NASHORN-365.js
+++ b/test/script/basic/NASHORN-365.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-366.js b/test/script/basic/NASHORN-366.js
index fae219bd..1c5626e7 100644
--- a/test/script/basic/NASHORN-366.js
+++ b/test/script/basic/NASHORN-366.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-368.js b/test/script/basic/NASHORN-368.js
index a1b1ba20..d84d94fa 100644
--- a/test/script/basic/NASHORN-368.js
+++ b/test/script/basic/NASHORN-368.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-37.js b/test/script/basic/NASHORN-37.js
index 74ee037d..8120c9d4 100644
--- a/test/script/basic/NASHORN-37.js
+++ b/test/script/basic/NASHORN-37.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-37 : object and array properties defined with special keys can be accessed be by special or string keys
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-375.js b/test/script/basic/NASHORN-375.js
index 6f841489..be19af15 100644
--- a/test/script/basic/NASHORN-375.js
+++ b/test/script/basic/NASHORN-375.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-376.js b/test/script/basic/NASHORN-376.js
index 37aa3450..7ad01176 100644
--- a/test/script/basic/NASHORN-376.js
+++ b/test/script/basic/NASHORN-376.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-377-big-endian.js b/test/script/basic/NASHORN-377-big-endian.js
new file mode 100644
index 00000000..30f0cc3e
--- /dev/null
+++ b/test/script/basic/NASHORN-377-big-endian.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * NASHORN-377: Typed arrays.
+ *
+ * @test
+ * @run
+ * @bigendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "NASHORN-377-payload.js");
diff --git a/test/script/basic/NASHORN-377-big-endian.js.EXPECTED b/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
new file mode 100644
index 00000000..ed3f19ab
--- /dev/null
+++ b/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
@@ -0,0 +1,34 @@
+8 8 true undefined
+[object ArrayBuffer] [object ArrayBuffer] [object Int8Array]
+0 8 8 1
+0 8 8 1
+0 8 8 1
+0 8 4 2
+0 8 4 2
+0 8 2 4
+0 8 2 4
+0 8 2 4
+0 8 1 8
+7071727374-807677 7071727374807677
+727374-807677 2 6
+72737480 2 4
+71727374 1 4
+717273748076
+7071727374807677 1886483059 1954575991
+70717273-1020305 1886483059 -16909061
+70717273fefdfcfb 1886483059 4278058235
+40490fdafefdfcfb 2
+400921fb4d12d84a 1
+400921fb4d12d84a 1074340347 1293080650
+00000000400921fb4d12d84a
+400921fb4d12-27b6 400921fb4d12d84a
+00-100804d12-27b6 ffff00804d12d84a
+0 1 2 3 4 5 6 7
+0102030405060708
+subarray(2,4)=0304 subarray(-6,-4)=0304
+010203040506
+03040506 0405
+0102030405060708090a0b0c0d0e0f10
+slice(4,8)=05060708 slice(-8,-4)=090a0b0c
+0102030405060708090a0b0c
+060708090a0b
diff --git a/test/script/basic/NASHORN-377-payload.js b/test/script/basic/NASHORN-377-payload.js
new file mode 100644
index 00000000..b47fb7cf
--- /dev/null
+++ b/test/script/basic/NASHORN-377-payload.js
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * NASHORN-377: Typed arrays. Payload for litte and big endian platforms.
+ *
+ * @subtest
+ * @run
+ */
+
+var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
+
+//---------------------------------------------------------------------------
+// utility functions
+//---------------------------------------------------------------------------
+function tohex(d, w) {
+ var hex = Number(d).toString(16);
+ var pad = (w ? w : 8) - hex.length;
+ hex = "00000000".substr(0, pad) + hex;
+ return hex;
+}
+
+function arrstr(a, n, w) {
+ var s = "";
+ if (typeof n == "undefined") n = a.length;
+ if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
+ for (var i = 0; i < n; i++) {
+ s += tohex(a[i], w);
+ }
+ return s;
+}
+function bufstr(b) {
+ if (b.buffer !== undefined) {
+ b = b.buffer;
+ }
+ return arrstr(new Uint8Array(b));
+}
+
+function assertFail(f) {
+ try {
+ f();
+ } catch (e) {
+ //print(e);
+ return;
+ }
+ throw "assertion failed: expected exception";
+}
+
+function assertTrue(f) {
+ if (f() !== true) throw "assertion failed: " + f;
+}
+
+function isUndefined(x) {
+ return typeof x === "undefined";
+}
+
+function fillArray(a, start) {
+ if (typeof start == "undefined") start = 1;
+ for (var i = 0; i < a.length; i++) {
+ a[i] = i + start;
+ }
+ return a;
+}
+
+//---------------------------------------------------------------------------
+// tests
+//---------------------------------------------------------------------------
+(function() {
+ var b = new ArrayBuffer(8);
+ var i8 = new Int8Array(b);
+ print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
+ print(b, i8.buffer, i8);
+})();
+
+(function test_attributes() {
+ var b = new ArrayBuffer(8);
+ for (var i in types) {
+ var x = new types[i](b);
+ print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
+ assertTrue(function(){ return x.constructor === types[i] });
+ }
+})();
+
+(function() {
+ var b = new ArrayBuffer(8);
+ var i8 = new Int8Array(b);
+ fillArray(i8, 0x70);
+
+ var i8_2 = new Int8Array(b, 2);
+ var i8_2_4 = new Uint8Array(b, 2, 4);
+
+ i8_2_4[3] = 0x80;
+
+ print(arrstr(i8, 8, 2) + " " + bufstr(i8));
+ print(arrstr(i8_2, 6) + " " + i8_2.byteOffset + " " + i8_2.byteLength);
+ print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
+
+ var i8_1_5 = i8.subarray(1, 5);
+ i8_2_4.subarray(1, 5);
+ print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
+
+ print(bufstr(b.slice(1,7)));
+})();
+
+(function() {
+ var b = new ArrayBuffer(8);
+ fillArray(new Int8Array(b), 0x70);
+ new Int8Array(b)[5] = 0x80;
+
+ var i32 = new Int32Array(b);
+ var u32 = new Uint32Array(b);
+ print(arrstr(i32), i32[0], i32[1]);
+ i32[1] = 0xfefdfcfb;
+ print(arrstr(i32), i32[0], i32[1]);
+ print(arrstr(u32), u32[0], u32[1]);
+
+ var pi = 3.1415926;
+ var f32 = new Float32Array(b);
+ var f64 = new Float64Array(b);
+ f32[0] = pi;
+ print(bufstr(b), f32.length);
+ f64[0] = pi;
+ print(bufstr(b), f64.length);
+ print(arrstr(u32), u32[0], u32[1]);
+
+ var d = new Int32Array(3);
+ d.set(i32,1);
+ print(bufstr(d));
+
+ var s = new Int16Array(b);
+ var t = new Uint16Array(b);
+ print(arrstr(s), arrstr(t));
+ s[0] = -1; s[1] = 0x80;
+ print(arrstr(s), arrstr(t));
+})();
+
+(function enumerate_properties() {
+ var i8 = new Int8Array(new ArrayBuffer(8));
+ var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
+})();
+
+// check that ScriptObject fallback is still working
+// DISABLED because correct behavior is unclear
+(function() {
+ // NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
+ var z = new Uint8Array(4);
+ z["asdf"] = "asdf"; print(z["asdf"]);
+ z[0x100000000] = "asdf"; print(z[0x100000000]);
+ z[-1] = "asdf"; print(z[-1]);
+
+ // v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
+ z[0xf0000000] = "asdf"; print(z[0xf0000000]);
+ z[0xffffffff] = "asdf"; print(z[0xffffffff]);
+ z[0x70000000] = "asdf"; print(z[0x70000000]);
+
+ // this will work in firefox and nashorn (not in v8).
+ Uint8Array.prototype[4] = "asdf"; print(z[4]);
+});
+
+(function test_exceptions() {
+ assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
+ assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
+ assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
+ assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
+})();
+
+(function test_subarray() {
+ var x = fillArray(new Int8Array(8));
+ print(arrstr(x));
+ print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
+ print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
+ assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
+ print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
+})();
+
+(function test_slice() {
+ var b = new ArrayBuffer(16);
+ fillArray(new Int8Array(b));
+ print(bufstr(b));
+ print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
+ print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
+ assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
+ print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
+})();
+
+(function test_clamped() {
+ var a = new Uint8ClampedArray(10);
+ a[0] = -17; // clamped to 0
+ a[1] = 4711; // clamped to 255
+ a[2] = 17.5; // clamped to 18
+ a[3] = 16.5; // clamped to 16
+ a[4] = 255.9; // clamped to 255
+ a[5] = Infinity; // clamped to 255
+ a[6] = -Infinity; // clamped to 0
+ a[7] = NaN; // 0
+ assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
+})();
+
+(function test_out_of_bounds() {
+ var a = new Int32Array(10);
+ a[10] = 10;
+ a[100] = 100;
+ a[1000] = 1000;
+ assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
+})();
+
diff --git a/test/script/basic/NASHORN-377.js b/test/script/basic/NASHORN-377.js
index 31d4df49..3484223f 100644
--- a/test/script/basic/NASHORN-377.js
+++ b/test/script/basic/NASHORN-377.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,201 +26,8 @@
*
* @test
* @run
+ * @littleendian
*/
-var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
-
-//---------------------------------------------------------------------------
-// utility functions
-//---------------------------------------------------------------------------
-function tohex(d, w) {
- var hex = Number(d).toString(16);
- var pad = (w ? w : 8) - hex.length;
- hex = "00000000".substr(0, pad) + hex;
- return hex;
-}
-
-function arrstr(a, n, w) {
- var s = "";
- if (typeof n == "undefined") n = a.length;
- if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
- for (var i = 0; i < n; i++) {
- s += tohex(a[i], w);
- }
- return s;
-}
-function bufstr(b) {
- if (b.buffer !== undefined) {
- b = b.buffer;
- }
- return arrstr(new Uint8Array(b));
-}
-
-function assertFail(f) {
- try {
- f();
- } catch (e) {
- //print(e);
- return;
- }
- throw "assertion failed: expected exception";
-}
-
-function assertTrue(f) {
- if (f() !== true) throw "assertion failed: " + f;
-}
-
-function isUndefined(x) {
- return typeof x === "undefined";
-}
-
-function fillArray(a, start) {
- if (typeof start == "undefined") start = 1;
- for (var i = 0; i < a.length; i++) {
- a[i] = i + start;
- }
- return a;
-}
-
-//---------------------------------------------------------------------------
-// tests
-//---------------------------------------------------------------------------
-(function() {
- var b = new ArrayBuffer(8);
- var i8 = new Int8Array(b);
- print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
- print(b, i8.buffer, i8);
-})();
-
-(function test_attributes() {
- var b = new ArrayBuffer(8);
- for (var i in types) {
- var x = new types[i](b);
- print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
- assertTrue(function(){ return x.constructor === types[i] });
- }
-})();
-
-(function() {
- var b = new ArrayBuffer(8);
- var i8 = new Int8Array(b);
- fillArray(i8, 0x70);
-
- var i8_2 = new Int8Array(b, 2);
- var i8_2_4 = new Uint8Array(b, 2, 4);
-
- i8_2_4[3] = 0x80;
-
- print(arrstr(i8, 8, 2) + " " + bufstr(i8));
- print(arrstr(i8_2, 6) + " " + i8_2.byteOffset + " " + i8_2.byteLength);
- print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
-
- var i8_1_5 = i8.subarray(1, 5);
- i8_2_4.subarray(1, 5);
- print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
-
- print(bufstr(b.slice(1,7)));
-})();
-
-(function() {
- var b = new ArrayBuffer(8);
- fillArray(new Int8Array(b), 0x70);
- new Int8Array(b)[5] = 0x80;
-
- var i32 = new Int32Array(b);
- var u32 = new Uint32Array(b);
- print(arrstr(i32), i32[0], i32[1]);
- i32[1] = 0xfefdfcfb;
- print(arrstr(i32), i32[0], i32[1]);
- print(arrstr(u32), u32[0], u32[1]);
-
- var pi = 3.1415926;
- var f32 = new Float32Array(b);
- var f64 = new Float64Array(b);
- f32[0] = pi;
- print(bufstr(b), f32.length);
- f64[0] = pi;
- print(bufstr(b), f64.length);
- print(arrstr(u32), u32[0], u32[1]);
-
- var d = new Int32Array(3);
- d.set(i32,1);
- print(bufstr(d));
-
- var s = new Int16Array(b);
- var t = new Uint16Array(b);
- print(arrstr(s), arrstr(t));
- s[0] = -1; s[1] = 0x80;
- print(arrstr(s), arrstr(t));
-})();
-
-(function enumerate_properties() {
- var i8 = new Int8Array(new ArrayBuffer(8));
- var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
-})();
-
-// check that ScriptObject fallback is still working
-// DISABLED because correct behavior is unclear
-(function() {
- // NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
- var z = new Uint8Array(4);
- z["asdf"] = "asdf"; print(z["asdf"]);
- z[0x100000000] = "asdf"; print(z[0x100000000]);
- z[-1] = "asdf"; print(z[-1]);
-
- // v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
- z[0xf0000000] = "asdf"; print(z[0xf0000000]);
- z[0xffffffff] = "asdf"; print(z[0xffffffff]);
- z[0x70000000] = "asdf"; print(z[0x70000000]);
-
- // this will work in firefox and nashorn (not in v8).
- Uint8Array.prototype[4] = "asdf"; print(z[4]);
-});
-
-(function test_exceptions() {
- assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
- assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
- assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
- assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
-})();
-
-(function test_subarray() {
- var x = fillArray(new Int8Array(8));
- print(arrstr(x));
- print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
- print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
- assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
- print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
-})();
-
-(function test_slice() {
- var b = ArrayBuffer(16);
- fillArray(new Int8Array(b));
- print(bufstr(b));
- print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
- print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
- assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
- print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
-})();
-
-(function test_clamped() {
- var a = new Uint8ClampedArray(10);
- a[0] = -17; // clamped to 0
- a[1] = 4711; // clamped to 255
- a[2] = 17.5; // clamped to 18
- a[3] = 16.5; // clamped to 16
- a[4] = 255.9; // clamped to 255
- a[5] = Infinity; // clamped to 255
- a[6] = -Infinity; // clamped to 0
- a[7] = NaN; // 0
- assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
-})();
-
-(function test_out_of_bounds() {
- var a = new Int32Array(10);
- a[10] = 10;
- a[100] = 100;
- a[1000] = 1000;
- assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
-})();
-
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "NASHORN-377-payload.js");
diff --git a/test/script/basic/NASHORN-378.js b/test/script/basic/NASHORN-378.js
index 0bf2a749..3508d290 100644
--- a/test/script/basic/NASHORN-378.js
+++ b/test/script/basic/NASHORN-378.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
var obj = {};
-Object.defineProperty(obj, "foo",
+Object.defineProperty(obj, "foo",
{ get: function() { return 42; },
configurable: true});
diff --git a/test/script/basic/NASHORN-38.js b/test/script/basic/NASHORN-38.js
index b02ecf7f..915b64d1 100644
--- a/test/script/basic/NASHORN-38.js
+++ b/test/script/basic/NASHORN-38.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,7 +33,7 @@ function func(){
// defined later in lexical order (see below)
print(typeof f);
return f;
-
+
function f(){
print("inside function 'f'");
}
diff --git a/test/script/basic/NASHORN-380.js b/test/script/basic/NASHORN-380.js
index e41380ec..252d8bbe 100644
--- a/test/script/basic/NASHORN-380.js
+++ b/test/script/basic/NASHORN-380.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-381.js b/test/script/basic/NASHORN-381.js
index 53237faf..f3e83d06 100644
--- a/test/script/basic/NASHORN-381.js
+++ b/test/script/basic/NASHORN-381.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-382.js b/test/script/basic/NASHORN-382.js
index 71ab3a55..f2882558 100644
--- a/test/script/basic/NASHORN-382.js
+++ b/test/script/basic/NASHORN-382.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-383.js b/test/script/basic/NASHORN-383.js
index ae1a06ec..5e329bcc 100644
--- a/test/script/basic/NASHORN-383.js
+++ b/test/script/basic/NASHORN-383.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-384.js b/test/script/basic/NASHORN-384.js
index 4c400502..3eedf6b2 100644
--- a/test/script/basic/NASHORN-384.js
+++ b/test/script/basic/NASHORN-384.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-385.js b/test/script/basic/NASHORN-385.js
index 27b328e9..05847170 100644
--- a/test/script/basic/NASHORN-385.js
+++ b/test/script/basic/NASHORN-385.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,7 +37,7 @@ function checkGetter() {
function checkSetter() {
o.bar = 44;
-}
+}
function checkCall() {
try {
@@ -51,8 +51,8 @@ checkGetter();
checkSetter();
checkCall();
-proto.__get__ = function(name) {
- print("in __get__: " + name);
+proto.__get__ = function(name) {
+ print("in __get__: " + name);
return name;
};
diff --git a/test/script/basic/NASHORN-389.js b/test/script/basic/NASHORN-389.js
index 71f9731c..555eb2ee 100644
--- a/test/script/basic/NASHORN-389.js
+++ b/test/script/basic/NASHORN-389.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-393.js b/test/script/basic/NASHORN-393.js
index 80f4083b..e8b1119e 100644
--- a/test/script/basic/NASHORN-393.js
+++ b/test/script/basic/NASHORN-393.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-394.js b/test/script/basic/NASHORN-394.js
index a265f169..259b8880 100644
--- a/test/script/basic/NASHORN-394.js
+++ b/test/script/basic/NASHORN-394.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-396.js b/test/script/basic/NASHORN-396.js
index 46bcf775..63b8ec2c 100644
--- a/test/script/basic/NASHORN-396.js
+++ b/test/script/basic/NASHORN-396.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,17 +27,17 @@
* @test
* @run
*/
-
-Object.defineProperty(Number.prototype,
- "foo",
+
+Object.defineProperty(Number.prototype,
+ "foo",
{ get: function () { 'use strict'; return this; }
-});
+});
if(!((5).foo === 5)) {
fail("#1 ToObject conversion on 'thisArg' for strict getter");
}
-Number.prototype.func = function() {
+Number.prototype.func = function() {
'use strict';
return this;
};
diff --git a/test/script/basic/NASHORN-397.js b/test/script/basic/NASHORN-397.js
index 63e7b3ac..fcfc5d80 100644
--- a/test/script/basic/NASHORN-397.js
+++ b/test/script/basic/NASHORN-397.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-398.js b/test/script/basic/NASHORN-398.js
index 6a0535f6..1246900a 100644
--- a/test/script/basic/NASHORN-398.js
+++ b/test/script/basic/NASHORN-398.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-40.js b/test/script/basic/NASHORN-40.js
index 34331ef2..6a5b3d56 100644
--- a/test/script/basic/NASHORN-40.js
+++ b/test/script/basic/NASHORN-40.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-400.js b/test/script/basic/NASHORN-400.js
index eabb8adf..272e3604 100644
--- a/test/script/basic/NASHORN-400.js
+++ b/test/script/basic/NASHORN-400.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-401.js b/test/script/basic/NASHORN-401.js
index 6a663e1a..eef1617e 100644
--- a/test/script/basic/NASHORN-401.js
+++ b/test/script/basic/NASHORN-401.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-402.js b/test/script/basic/NASHORN-402.js
index 33c02a19..8586219f 100644
--- a/test/script/basic/NASHORN-402.js
+++ b/test/script/basic/NASHORN-402.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-404.js b/test/script/basic/NASHORN-404.js
index 672fe89c..2e4ab899 100644
--- a/test/script/basic/NASHORN-404.js
+++ b/test/script/basic/NASHORN-404.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-405.js b/test/script/basic/NASHORN-405.js
index c1049243..5c304c5c 100644
--- a/test/script/basic/NASHORN-405.js
+++ b/test/script/basic/NASHORN-405.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,13 +23,13 @@
/**
* NASHORN-405 make sure slice does not modify arrays
- *
+ *
* @test
* @run
*/
var x = ['foo', '%zx'];
-var s = x.slice(1);
+var s = x.slice(1);
print(s);
print(x);
diff --git a/test/script/basic/NASHORN-406.js b/test/script/basic/NASHORN-406.js
index a1f362fe..09f677c9 100644
--- a/test/script/basic/NASHORN-406.js
+++ b/test/script/basic/NASHORN-406.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-406 : Property descriptor properties should be enumerable
+ * NASHORN-406 : Property descriptor properties should be enumerable
*
* @test
* @run
@@ -36,7 +36,7 @@ var obj = {
function checkData() {
var desc = Object.getOwnPropertyDescriptor(obj, "foo");
- var enumSeen = false, writeSeen = false,
+ var enumSeen = false, writeSeen = false,
configSeen = false, valueSeen = false;
for (i in desc) {
switch(i) {
@@ -50,7 +50,7 @@ function checkData() {
valueSeen = true; break;
}
}
-
+
return enumSeen && writeSeen && configSeen && valueSeen;
}
@@ -60,7 +60,7 @@ if (!checkData()) {
function checkAccessor() {
var desc = Object.getOwnPropertyDescriptor(obj, "bar");
- var enumSeen = false, getterSeen = false,
+ var enumSeen = false, getterSeen = false,
configSeen = false, setterSeen = false;
for (i in desc) {
switch(i) {
diff --git a/test/script/basic/NASHORN-408.js b/test/script/basic/NASHORN-408.js
index 1c3375c3..4251ed64 100644
--- a/test/script/basic/NASHORN-408.js
+++ b/test/script/basic/NASHORN-408.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-415.js b/test/script/basic/NASHORN-415.js
index 6f29f1a1..f2533bcc 100644
--- a/test/script/basic/NASHORN-415.js
+++ b/test/script/basic/NASHORN-415.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-416.js b/test/script/basic/NASHORN-416.js
index 387629a7..86e26401 100644
--- a/test/script/basic/NASHORN-416.js
+++ b/test/script/basic/NASHORN-416.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@ var obj = {}
function getter() { return 32; }
-Object.defineProperty(obj, "foo",
+Object.defineProperty(obj, "foo",
{ get: getter, configurable: true });
function setter(x) { print(x); }
diff --git a/test/script/basic/NASHORN-417.js b/test/script/basic/NASHORN-417.js
index 6148f060..5a4f4414 100644
--- a/test/script/basic/NASHORN-417.js
+++ b/test/script/basic/NASHORN-417.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-418.js b/test/script/basic/NASHORN-418.js
index b42bd832..563b3d73 100644
--- a/test/script/basic/NASHORN-418.js
+++ b/test/script/basic/NASHORN-418.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-420.js b/test/script/basic/NASHORN-420.js
index 741b940e..7ccb919c 100644
--- a/test/script/basic/NASHORN-420.js
+++ b/test/script/basic/NASHORN-420.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-421.js b/test/script/basic/NASHORN-421.js
index 3a81fe64..9899eae1 100644
--- a/test/script/basic/NASHORN-421.js
+++ b/test/script/basic/NASHORN-421.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -52,9 +52,9 @@ function checkNull(name) {
}
}
-var methods = [ "concat", "join", "pop", "push", "reverse",
+var methods = [ "concat", "join", "pop", "push", "reverse",
"shift", "unshift", "slice", "sort", "splice",
- "indexOf", "lastIndexOf", "every", "some", "forEach",
+ "indexOf", "lastIndexOf", "every", "some", "forEach",
"map", "filter", "reduce", "reduceRight" ];
for (var m in methods) {
diff --git a/test/script/basic/NASHORN-423.js b/test/script/basic/NASHORN-423.js
index 7fa1b00b..62ab4767 100644
--- a/test/script/basic/NASHORN-423.js
+++ b/test/script/basic/NASHORN-423.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-423a.js b/test/script/basic/NASHORN-423a.js
index bbab24f1..7aebefb6 100644
--- a/test/script/basic/NASHORN-423a.js
+++ b/test/script/basic/NASHORN-423a.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-424.js b/test/script/basic/NASHORN-424.js
index 1bcbe19d..86d293bc 100644
--- a/test/script/basic/NASHORN-424.js
+++ b/test/script/basic/NASHORN-424.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-425.js b/test/script/basic/NASHORN-425.js
index c81aea2c..d1467bbe 100644
--- a/test/script/basic/NASHORN-425.js
+++ b/test/script/basic/NASHORN-425.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-426.js b/test/script/basic/NASHORN-426.js
index 2d4ee7e8..4ddf29e1 100644
--- a/test/script/basic/NASHORN-426.js
+++ b/test/script/basic/NASHORN-426.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-427.js b/test/script/basic/NASHORN-427.js
index 0169ce86..bbebfe4e 100644
--- a/test/script/basic/NASHORN-427.js
+++ b/test/script/basic/NASHORN-427.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-428.js b/test/script/basic/NASHORN-428.js
index 3d692d1b..ff3390da 100644
--- a/test/script/basic/NASHORN-428.js
+++ b/test/script/basic/NASHORN-428.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-429.js b/test/script/basic/NASHORN-429.js
index 45917058..b58bff2a 100644
--- a/test/script/basic/NASHORN-429.js
+++ b/test/script/basic/NASHORN-429.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-432.js b/test/script/basic/NASHORN-432.js
index d14ee73c..6f6e7f15 100644
--- a/test/script/basic/NASHORN-432.js
+++ b/test/script/basic/NASHORN-432.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-433.js b/test/script/basic/NASHORN-433.js
index 99b88a8e..25850bb3 100644
--- a/test/script/basic/NASHORN-433.js
+++ b/test/script/basic/NASHORN-433.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-434.js b/test/script/basic/NASHORN-434.js
index 41374690..03f0f57b 100644
--- a/test/script/basic/NASHORN-434.js
+++ b/test/script/basic/NASHORN-434.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,7 +34,7 @@ function func(val, idx, obj) {
if (this !== global) {
fail("#1 callback got 'this' different from global");
}
-}
+}
function strictFunc(val, idx, obj) {
'use strict';
@@ -49,7 +49,7 @@ function strictFunc(val, idx, obj) {
}
var arr = [1];
-arr.forEach(func);
+arr.forEach(func);
arr.forEach(strictFunc);
var callbackThis = {};
diff --git a/test/script/basic/NASHORN-435.js b/test/script/basic/NASHORN-435.js
index 15d7bf00..91a64e66 100644
--- a/test/script/basic/NASHORN-435.js
+++ b/test/script/basic/NASHORN-435.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-437.js b/test/script/basic/NASHORN-437.js
index cf23361c..59c1e74d 100644
--- a/test/script/basic/NASHORN-437.js
+++ b/test/script/basic/NASHORN-437.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-44.js b/test/script/basic/NASHORN-44.js
index 10b58c2d..9e82e1b0 100644
--- a/test/script/basic/NASHORN-44.js
+++ b/test/script/basic/NASHORN-44.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,9 +29,9 @@
*/
function loop1() {
print("loop1");
- for (var i = 0; i < 5; i++) {
- print(i);
- continue;
+ for (var i = 0; i < 5; i++) {
+ print(i);
+ continue;
}
print(i);
print("done1");
@@ -40,8 +40,8 @@ function loop1() {
function loop2() {
print("loop2");
for (var i = 0; i < 5; i++) {
- print(i);
- break;
+ print(i);
+ break;
}
print(i);
print("done2");
diff --git a/test/script/basic/NASHORN-441.js b/test/script/basic/NASHORN-441.js
index 8c51ea98..7e9d3162 100644
--- a/test/script/basic/NASHORN-441.js
+++ b/test/script/basic/NASHORN-441.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-442.js b/test/script/basic/NASHORN-442.js
index 9a5128a6..13f3c345 100644
--- a/test/script/basic/NASHORN-442.js
+++ b/test/script/basic/NASHORN-442.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-443.js b/test/script/basic/NASHORN-443.js
index ab918207..d585ebc6 100644
--- a/test/script/basic/NASHORN-443.js
+++ b/test/script/basic/NASHORN-443.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-444.js b/test/script/basic/NASHORN-444.js
index 27811af6..24546f45 100644
--- a/test/script/basic/NASHORN-444.js
+++ b/test/script/basic/NASHORN-444.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-445.js b/test/script/basic/NASHORN-445.js
index 89a1b721..c615c238 100644
--- a/test/script/basic/NASHORN-445.js
+++ b/test/script/basic/NASHORN-445.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-446.js b/test/script/basic/NASHORN-446.js
index f8ba093c..20ee683f 100644
--- a/test/script/basic/NASHORN-446.js
+++ b/test/script/basic/NASHORN-446.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-447.js b/test/script/basic/NASHORN-447.js
index e817c7f6..8f6100e4 100644
--- a/test/script/basic/NASHORN-447.js
+++ b/test/script/basic/NASHORN-447.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-448.js b/test/script/basic/NASHORN-448.js
index a79adf9c..5618c369 100644
--- a/test/script/basic/NASHORN-448.js
+++ b/test/script/basic/NASHORN-448.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-449.js b/test/script/basic/NASHORN-449.js
index ef7171a5..27a19db1 100644
--- a/test/script/basic/NASHORN-449.js
+++ b/test/script/basic/NASHORN-449.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-449 : defineProperty on arguments object does not work element in question was deleted earlier
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/NASHORN-45.js b/test/script/basic/NASHORN-45.js
index 29105b76..9d532dc5 100644
--- a/test/script/basic/NASHORN-45.js
+++ b/test/script/basic/NASHORN-45.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-450.js b/test/script/basic/NASHORN-450.js
index eb3776d7..77c25a02 100644
--- a/test/script/basic/NASHORN-450.js
+++ b/test/script/basic/NASHORN-450.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-452.js b/test/script/basic/NASHORN-452.js
index aa2ef5c0..83d7747d 100644
--- a/test/script/basic/NASHORN-452.js
+++ b/test/script/basic/NASHORN-452.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-459.js b/test/script/basic/NASHORN-459.js
index 6d9258e3..f6bcc54d 100644
--- a/test/script/basic/NASHORN-459.js
+++ b/test/script/basic/NASHORN-459.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-46.js b/test/script/basic/NASHORN-46.js
index a23a2a06..008992ae 100644
--- a/test/script/basic/NASHORN-46.js
+++ b/test/script/basic/NASHORN-46.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-462.js b/test/script/basic/NASHORN-462.js
index 6cfbb831..078a85f5 100644
--- a/test/script/basic/NASHORN-462.js
+++ b/test/script/basic/NASHORN-462.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,8 +31,8 @@
function Foo() {};
Object.defineProperty(Foo.prototype, "bar", { value: 19 });
-var fooObj = new Foo();
-fooObj.bar = "overridden";
+var fooObj = new Foo();
+fooObj.bar = "overridden";
if (fooObj.hasOwnProperty("bar")) {
fail("inherited non-writable property can be overridden");
}
diff --git a/test/script/basic/NASHORN-463.js b/test/script/basic/NASHORN-463.js
index 41ca3fb5..5b58f5a2 100644
--- a/test/script/basic/NASHORN-463.js
+++ b/test/script/basic/NASHORN-463.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-468.js b/test/script/basic/NASHORN-468.js
index 10a36f99..392fd099 100644
--- a/test/script/basic/NASHORN-468.js
+++ b/test/script/basic/NASHORN-468.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-47.js b/test/script/basic/NASHORN-47.js
index 1454db03..43210e7e 100644
--- a/test/script/basic/NASHORN-47.js
+++ b/test/script/basic/NASHORN-47.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-473.js b/test/script/basic/NASHORN-473.js
index 1b935aed..79615e50 100644
--- a/test/script/basic/NASHORN-473.js
+++ b/test/script/basic/NASHORN-473.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-474.js b/test/script/basic/NASHORN-474.js
index 3df4aa4d..69b351f1 100644
--- a/test/script/basic/NASHORN-474.js
+++ b/test/script/basic/NASHORN-474.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-478.js b/test/script/basic/NASHORN-478.js
index 945d2b57..dd851bcf 100644
--- a/test/script/basic/NASHORN-478.js
+++ b/test/script/basic/NASHORN-478.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-48.js b/test/script/basic/NASHORN-48.js
index 1bbba137..9fe40761 100644
--- a/test/script/basic/NASHORN-48.js
+++ b/test/script/basic/NASHORN-48.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,9 +29,9 @@
*/
function loop3() {
- for (var i = 0; i < 5; i++) {
- print(i);
- throw "ERROR";
+ for (var i = 0; i < 5; i++) {
+ print(i);
+ throw "ERROR";
}
print("dead");
}
@@ -41,17 +41,17 @@ try {
} catch (e) {
print(e);
}
-
+
function loop4() {
var i = 0;
while (i++ < 5) {
- print(i);
- throw "ERROR";
+ print(i);
+ throw "ERROR";
}
print("dead");
}
-try {
+try {
loop4();
} catch (e) {
print(e);
@@ -60,13 +60,13 @@ try {
function loop5() {
var i = 0;
do {
- print(i);
- throw "ERROR";
+ print(i);
+ throw "ERROR";
} while (i++ < 5);
print("dead");
}
-try {
+try {
loop5();
} catch (e) {
print(e);
diff --git a/test/script/basic/NASHORN-481.js b/test/script/basic/NASHORN-481.js
index 42295fa1..571b7bfb 100644
--- a/test/script/basic/NASHORN-481.js
+++ b/test/script/basic/NASHORN-481.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -10029,7 +10029,7 @@ var largeTable = [
"tag": "mesoventral",
"popularity": 4096
}];
-
+
var entry = largeTable[1000];
print(entry.tag, entry.popularity);
diff --git a/test/script/basic/NASHORN-482.js b/test/script/basic/NASHORN-482.js
index 76afb59e..b3e0344d 100644
--- a/test/script/basic/NASHORN-482.js
+++ b/test/script/basic/NASHORN-482.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-484.js b/test/script/basic/NASHORN-484.js
index b1f0a0ed..ec8a20f1 100644
--- a/test/script/basic/NASHORN-484.js
+++ b/test/script/basic/NASHORN-484.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-486.js b/test/script/basic/NASHORN-486.js
index f03f0963..e0d7bda8 100644
--- a/test/script/basic/NASHORN-486.js
+++ b/test/script/basic/NASHORN-486.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@ var fileName = __FILE__;
try {
// save line number and force ReferenceError for 'foo'
- var lineNumber = __LINE__; print(foo);
+ var lineNumber = __LINE__; print(foo);
fail("#1 should have thrown ReferenceError");
} catch (e) {
if (! (e instanceof ReferenceError)) {
diff --git a/test/script/basic/NASHORN-487.js b/test/script/basic/NASHORN-487.js
index c5685919..38d020dc 100644
--- a/test/script/basic/NASHORN-487.js
+++ b/test/script/basic/NASHORN-487.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-488.js b/test/script/basic/NASHORN-488.js
index 53bb8882..342630f2 100644
--- a/test/script/basic/NASHORN-488.js
+++ b/test/script/basic/NASHORN-488.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,7 +34,7 @@ if (desc !== undefined) {
}
Object.defineProperty(Function.prototype, "prototype", {
- set: undefined, get: function() { return 32; },
+ set: undefined, get: function() { return 32; },
configurable: true
});
diff --git a/test/script/basic/NASHORN-49.js b/test/script/basic/NASHORN-49.js
index 1b4a68ca..e90444a3 100644
--- a/test/script/basic/NASHORN-49.js
+++ b/test/script/basic/NASHORN-49.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-490.js b/test/script/basic/NASHORN-490.js
index e9bdd931..1966d378 100644
--- a/test/script/basic/NASHORN-490.js
+++ b/test/script/basic/NASHORN-490.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-494.js b/test/script/basic/NASHORN-494.js
index 18d19c8c..ac652dac 100644
--- a/test/script/basic/NASHORN-494.js
+++ b/test/script/basic/NASHORN-494.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-497.js b/test/script/basic/NASHORN-497.js
index ad8b4eb9..294bdb26 100644
--- a/test/script/basic/NASHORN-497.js
+++ b/test/script/basic/NASHORN-497.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-498.js b/test/script/basic/NASHORN-498.js
index 63047885..ad156db3 100644
--- a/test/script/basic/NASHORN-498.js
+++ b/test/script/basic/NASHORN-498.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,13 +30,13 @@
// no syntax error expected for the following functions
function func() {
- // Parser thinks it is a for-in statement! But 'in' used in
+ // Parser thinks it is a for-in statement! But 'in' used in
// cond. expression. This is a normal for statement
for (var x = a ? b in c : 3;;) {}
}
function func2() {
- // for-in statement but init is cond. expression with 'in'
+ // for-in statement but init is cond. expression with 'in'
// This is same as "for (var x = (a? b in c : e) in {} )"
for (var x = a ? b in c : e in {}) {}
}
diff --git a/test/script/basic/NASHORN-499.js b/test/script/basic/NASHORN-499.js
index bbedb05e..34837758 100644
--- a/test/script/basic/NASHORN-499.js
+++ b/test/script/basic/NASHORN-499.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-50.js b/test/script/basic/NASHORN-50.js
index 7292b958..08f8fdd7 100644
--- a/test/script/basic/NASHORN-50.js
+++ b/test/script/basic/NASHORN-50.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
try {
for (var y in null) {
- y = 2;
+ y = 2;
}
} catch (e) {
print(e);
@@ -38,7 +38,7 @@ try {
try {
for (var y in undefined) {
- y = 2;
+ y = 2;
}
} catch (e) {
print(e);
diff --git a/test/script/basic/NASHORN-500.js b/test/script/basic/NASHORN-500.js
index 30546e8b..62444b97 100644
--- a/test/script/basic/NASHORN-500.js
+++ b/test/script/basic/NASHORN-500.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,7 +29,7 @@
*/
var origToString = Object.prototype.toString;
-Object.prototype.toString = function () {
+Object.prototype.toString = function () {
return this.myStr();
}
diff --git a/test/script/basic/NASHORN-503.js b/test/script/basic/NASHORN-503.js
index 50838817..f1a01d83 100644
--- a/test/script/basic/NASHORN-503.js
+++ b/test/script/basic/NASHORN-503.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-51.js b/test/script/basic/NASHORN-51.js
index 45d00e9e..6cf68a4e 100644
--- a/test/script/basic/NASHORN-51.js
+++ b/test/script/basic/NASHORN-51.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-511.js b/test/script/basic/NASHORN-511.js
index edac1a9a..c382468d 100644
--- a/test/script/basic/NASHORN-511.js
+++ b/test/script/basic/NASHORN-511.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-515.js b/test/script/basic/NASHORN-515.js
index 198be1f3..09a6b7a7 100644
--- a/test/script/basic/NASHORN-515.js
+++ b/test/script/basic/NASHORN-515.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,17 +30,17 @@
function a() {
var x = (3.14-2.14);
-
+
switch (x) {
case 1:
- print("--1");
- break;
+ print("--1");
+ break;
case 2:
- print("--2");
- break;
+ print("--2");
+ break;
default:
- print("default");
- break;
+ print("default");
+ break;
}
}
@@ -50,11 +50,11 @@ function b() {
switch (index) {
case 0x00:
case 0x01:
- print("one zero");
- break;
+ print("one zero");
+ break;
default:
- print("default");
- break;
+ print("default");
+ break;
}
}
@@ -64,76 +64,76 @@ function c() {
switch (index) {
case 0x00:
case 0x01:
- print("one zero");
- break;
+ print("one zero");
+ break;
default:
- print("default");
+ print("default");
}
--index;
}
function d() {
var x = (3.14-1.14);
-
+
switch(x) {
case 1:
- print("--1"); break;
+ print("--1"); break;
case 2:
- print("--2"); break;
+ print("--2"); break;
case 3:
- print("--3"); break;
+ print("--3"); break;
case 4:
- print("--4"); break;
+ print("--4"); break;
default:
- print("default");
+ print("default");
}
}
function e() {
var y = 2147483647;
-
+
switch(y) {
case -2147483648:
- print("MIN_INT"); break;
+ print("MIN_INT"); break;
case -2147483647:
- print("MIN_INT+1"); break;
+ print("MIN_INT+1"); break;
case 2147483647:
- print("MAX_INT"); break;
+ print("MAX_INT"); break;
case 1:
- print("--1"); break;
+ print("--1"); break;
case 2:
- print("--2"); break;
+ print("--2"); break;
case 3:
- print("--3"); break;
+ print("--3"); break;
case 4:
- print("--4"); break;
+ print("--4"); break;
default:
- print("default");
+ print("default");
}
}
function f() {
var z = 2;
-
+
switch(z) {
case -2147483648:
- print("MIN_INT"); break;
+ print("MIN_INT"); break;
case -2147483647:
- print("MIN_INT+1"); break;
+ print("MIN_INT+1"); break;
case 2147483647:
- print("MAX_INT"); break;
+ print("MAX_INT"); break;
case 1:
- print("--1"); break;
+ print("--1"); break;
case 2:
- print("--2 first"); break;
+ print("--2 first"); break;
case 2:
- print("--2 second"); break;
+ print("--2 second"); break;
case 3:
- print("--3"); break;
+ print("--3"); break;
case 4:
- print("--4"); break;
+ print("--4"); break;
default:
- print("default");
+ print("default");
}
}
diff --git a/test/script/basic/NASHORN-516.js b/test/script/basic/NASHORN-516.js
index f369b9cb..04d2bfd1 100644
--- a/test/script/basic/NASHORN-516.js
+++ b/test/script/basic/NASHORN-516.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-52.js b/test/script/basic/NASHORN-52.js
index 1727e022..2dc449ee 100644
--- a/test/script/basic/NASHORN-52.js
+++ b/test/script/basic/NASHORN-52.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-534.js b/test/script/basic/NASHORN-534.js
index ab7a9b9d..3124f435 100644
--- a/test/script/basic/NASHORN-534.js
+++ b/test/script/basic/NASHORN-534.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-535.js b/test/script/basic/NASHORN-535.js
index 57abfc40..93ae82f2 100644
--- a/test/script/basic/NASHORN-535.js
+++ b/test/script/basic/NASHORN-535.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-544.js b/test/script/basic/NASHORN-544.js
index 87c6cae5..34f46ca8 100644
--- a/test/script/basic/NASHORN-544.js
+++ b/test/script/basic/NASHORN-544.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-55.js b/test/script/basic/NASHORN-55.js
index 58576a11..0d7fa071 100644
--- a/test/script/basic/NASHORN-55.js
+++ b/test/script/basic/NASHORN-55.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-554.js b/test/script/basic/NASHORN-554.js
index 4c7ae871..87d49ec5 100644
--- a/test/script/basic/NASHORN-554.js
+++ b/test/script/basic/NASHORN-554.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-556.js b/test/script/basic/NASHORN-556.js
index 1332d02b..3ddd20b6 100644
--- a/test/script/basic/NASHORN-556.js
+++ b/test/script/basic/NASHORN-556.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-56.js b/test/script/basic/NASHORN-56.js
index 47228452..7895a8e5 100644
--- a/test/script/basic/NASHORN-56.js
+++ b/test/script/basic/NASHORN-56.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-562.js b/test/script/basic/NASHORN-562.js
index 2754cbab..4fd9dc3a 100644
--- a/test/script/basic/NASHORN-562.js
+++ b/test/script/basic/NASHORN-562.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-565.js b/test/script/basic/NASHORN-565.js
index ad789ce1..79bd0127 100644
--- a/test/script/basic/NASHORN-565.js
+++ b/test/script/basic/NASHORN-565.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-575.js b/test/script/basic/NASHORN-575.js
index 4eda079c..6341ffe3 100644
--- a/test/script/basic/NASHORN-575.js
+++ b/test/script/basic/NASHORN-575.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-58.js b/test/script/basic/NASHORN-58.js
index b0aeaa4f..1a55c3bc 100644
--- a/test/script/basic/NASHORN-58.js
+++ b/test/script/basic/NASHORN-58.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,14 +30,14 @@
function test1() {
var x = 1;
- try {
- print('try');
- x = 2;
+ try {
+ print('try');
+ x = 2;
} catch(e) {
- print('catch');
- } finally {
- print('finally');
- x = 3;
+ print('catch');
+ } finally {
+ print('finally');
+ x = 3;
}
print(x);
}
@@ -45,81 +45,81 @@ function test1() {
function test2() {
var x = 1;
try {
- print('try');
+ print('try');
} finally {
- print('finally');
- x = 2;
+ print('finally');
+ x = 2;
}
print(x);
}
function test3() {
try {
- return 2;
+ return 2;
} finally {
- return 3;
+ return 3;
}
}
function test4() {
try {
- x = 1;
- print(x);
- try {
- x = 2;
- print(x);
- } finally {
- x = 3;
- print(x)
- try {
- x = 4;
- print(x);
- } finally {
- x = 5;
- print(x);
- }
- }
- print(x)
+ x = 1;
+ print(x);
+ try {
+ x = 2;
+ print(x);
} finally {
- x = 6;
- print(x);
+ x = 3;
+ print(x)
+ try {
+ x = 4;
+ print(x);
+ } finally {
+ x = 5;
+ print(x);
+ }
+ }
+ print(x)
+ } finally {
+ x = 6;
+ print(x);
}
print(x);
}
function test5() {
try {
- x = 1;
- print(x);
- try {
- x = 2;
- print(x);
- } finally {
- x = 3;
- print(x)
- try {
- x = 4;
- print(x);
- } finally {
- x = 5;
- return x;
- }
- }
- print(x)
+ x = 1;
+ print(x);
+ try {
+ x = 2;
+ print(x);
+ } finally {
+ x = 3;
+ print(x)
+ try {
+ x = 4;
+ print(x);
+ } finally {
+ x = 5;
+ return x;
+ }
+ }
+ print(x)
} finally {
- x = 6;
- return x;
+ x = 6;
+ return x;
}
}
function test6() {
try {
- throw new Error("testing");
+ throw new Error("testing");
} catch (ex) {
- print(ex);
- return;
+ print(ex);
+ return;
} finally {
- print("finally");
+ print("finally");
}
}
@@ -133,7 +133,7 @@ function test7() {
i++;
}
if (i != 4) {
- print("FAIL");
+ print("FAIL");
}
print("SUCCESS");
}
diff --git a/test/script/basic/NASHORN-59.js b/test/script/basic/NASHORN-59.js
index 1379fa6d..3a1c6ebd 100644
--- a/test/script/basic/NASHORN-59.js
+++ b/test/script/basic/NASHORN-59.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-592-dual.js b/test/script/basic/NASHORN-592-dual.js
index 73dd8151..e7c5ed3e 100644
--- a/test/script/basic/NASHORN-592-dual.js
+++ b/test/script/basic/NASHORN-592-dual.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-592.js b/test/script/basic/NASHORN-592.js
index cbc29841..99a20068 100644
--- a/test/script/basic/NASHORN-592.js
+++ b/test/script/basic/NASHORN-592.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-597.js b/test/script/basic/NASHORN-597.js
index 7195b055..f413d5f1 100644
--- a/test/script/basic/NASHORN-597.js
+++ b/test/script/basic/NASHORN-597.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-60.js b/test/script/basic/NASHORN-60.js
index 338c237f..e1a5e727 100644
--- a/test/script/basic/NASHORN-60.js
+++ b/test/script/basic/NASHORN-60.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-609.js b/test/script/basic/NASHORN-609.js
index 5c84f018..d6c22a0f 100644
--- a/test/script/basic/NASHORN-609.js
+++ b/test/script/basic/NASHORN-609.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-61.js b/test/script/basic/NASHORN-61.js
index 0c7f2354..4444b50c 100644
--- a/test/script/basic/NASHORN-61.js
+++ b/test/script/basic/NASHORN-61.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-62.js b/test/script/basic/NASHORN-62.js
index a3ba6e26..bb8a6500 100644
--- a/test/script/basic/NASHORN-62.js
+++ b/test/script/basic/NASHORN-62.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-620.js b/test/script/basic/NASHORN-620.js
index ce99528e..94ee9c6c 100644
--- a/test/script/basic/NASHORN-620.js
+++ b/test/script/basic/NASHORN-620.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-623.js b/test/script/basic/NASHORN-623.js
index 8ecdb134..31c6f71f 100644
--- a/test/script/basic/NASHORN-623.js
+++ b/test/script/basic/NASHORN-623.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-627.js b/test/script/basic/NASHORN-627.js
index 07662ff0..995cb4f4 100644
--- a/test/script/basic/NASHORN-627.js
+++ b/test/script/basic/NASHORN-627.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-63.js b/test/script/basic/NASHORN-63.js
index f1178de5..83df17ef 100644
--- a/test/script/basic/NASHORN-63.js
+++ b/test/script/basic/NASHORN-63.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -64,7 +64,7 @@ if ((new Object() != new Object()) !== true) {
error('Different Objects are equal');
}
-var obj1 = {};
+var obj1 = {};
var obj2 = obj1;
if (obj1 != obj2) {
error(' Same object literals are not equal');
diff --git a/test/script/basic/NASHORN-637.js b/test/script/basic/NASHORN-637.js
index 606d8932..00134a4d 100644
--- a/test/script/basic/NASHORN-637.js
+++ b/test/script/basic/NASHORN-637.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-639.js b/test/script/basic/NASHORN-639.js
index fcc02e09..6047b02f 100644
--- a/test/script/basic/NASHORN-639.js
+++ b/test/script/basic/NASHORN-639.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-64.js b/test/script/basic/NASHORN-64.js
index 03d95b2b..de062ef2 100644
--- a/test/script/basic/NASHORN-64.js
+++ b/test/script/basic/NASHORN-64.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-642.js b/test/script/basic/NASHORN-642.js
index acbd6025..a751c189 100644
--- a/test/script/basic/NASHORN-642.js
+++ b/test/script/basic/NASHORN-642.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-646.js b/test/script/basic/NASHORN-646.js
index 493a7986..37022880 100644
--- a/test/script/basic/NASHORN-646.js
+++ b/test/script/basic/NASHORN-646.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-658.js b/test/script/basic/NASHORN-658.js
index 13e5e29a..2d5a8ad3 100644
--- a/test/script/basic/NASHORN-658.js
+++ b/test/script/basic/NASHORN-658.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-659.js b/test/script/basic/NASHORN-659.js
index 7c6c1502..2abe992b 100644
--- a/test/script/basic/NASHORN-659.js
+++ b/test/script/basic/NASHORN-659.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-66.js b/test/script/basic/NASHORN-66.js
index f1455ff2..88608534 100644
--- a/test/script/basic/NASHORN-66.js
+++ b/test/script/basic/NASHORN-66.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-664.js b/test/script/basic/NASHORN-664.js
index 268d5df8..4856004a 100644
--- a/test/script/basic/NASHORN-664.js
+++ b/test/script/basic/NASHORN-664.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,11 +34,11 @@ try {
e.fileName = "foo";
if (e.fileName !== 'foo') {
fail("can not set e.fileName");
- }
+ }
e.lineNumber = 100;
if (e.lineNumber !== 100) {
fail("can not set e.lineNumber");
- }
+ }
e.columnNumber = 33;
if (e.columnNumber !== 33) {
fail("can not set e.columnNumber");
diff --git a/test/script/basic/NASHORN-665.js b/test/script/basic/NASHORN-665.js
index 54e7f084..c1b8a289 100644
--- a/test/script/basic/NASHORN-665.js
+++ b/test/script/basic/NASHORN-665.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-67.js b/test/script/basic/NASHORN-67.js
index b273b424..33fbd494 100644
--- a/test/script/basic/NASHORN-67.js
+++ b/test/script/basic/NASHORN-67.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,15 +30,15 @@
function test_nested() {
try {
- try {
- throw new Error("bam!");
- } catch (e) {
- print("SUCCESS")
- }
+ try {
+ throw new Error("bam!");
+ } catch (e) {
+ print("SUCCESS")
+ }
} catch (e2) {
- fail("inner catch should have caught the exception");
- }
-
+ fail("inner catch should have caught the exception");
+ }
+
}
test_nested()
diff --git a/test/script/basic/NASHORN-678.js b/test/script/basic/NASHORN-678.js
index e585eb8d..e40ef170 100644
--- a/test/script/basic/NASHORN-678.js
+++ b/test/script/basic/NASHORN-678.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -41,7 +41,7 @@ if ((33).toString() !== "33") {
try {
33();
- fail("should have thrown error");
+ fail("should have thrown error");
} catch (e) {
if (! (e instanceof TypeError)) {
fail("expected TypeError, got " + e);
diff --git a/test/script/basic/NASHORN-68.js b/test/script/basic/NASHORN-68.js
index d56da368..31fa3e53 100644
--- a/test/script/basic/NASHORN-68.js
+++ b/test/script/basic/NASHORN-68.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-689.js b/test/script/basic/NASHORN-689.js
index 938b111e..1a49e8ea 100644
--- a/test/script/basic/NASHORN-689.js
+++ b/test/script/basic/NASHORN-689.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-69.js b/test/script/basic/NASHORN-69.js
index 9ec39a3a..aeefaf0a 100644
--- a/test/script/basic/NASHORN-69.js
+++ b/test/script/basic/NASHORN-69.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-691.js b/test/script/basic/NASHORN-691.js
index ec36eeda..3a7b9f3e 100644
--- a/test/script/basic/NASHORN-691.js
+++ b/test/script/basic/NASHORN-691.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-694.js b/test/script/basic/NASHORN-694.js
index eb1d294f..3beb2816 100644
--- a/test/script/basic/NASHORN-694.js
+++ b/test/script/basic/NASHORN-694.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-697.js b/test/script/basic/NASHORN-697.js
index 012f33b4..f88e271f 100644
--- a/test/script/basic/NASHORN-697.js
+++ b/test/script/basic/NASHORN-697.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-703.js b/test/script/basic/NASHORN-703.js
index 41d3570c..4d74976b 100644
--- a/test/script/basic/NASHORN-703.js
+++ b/test/script/basic/NASHORN-703.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@
* This file is split into two tests as the presence of eval affects the whole script
*
* @test
- * @run
+ * @run
*/
function template() {
diff --git a/test/script/basic/NASHORN-703a.js b/test/script/basic/NASHORN-703a.js
index 18c26a44..d24d2bd6 100644
--- a/test/script/basic/NASHORN-703a.js
+++ b/test/script/basic/NASHORN-703a.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@
* This file is split into two tests as the presence of eval affects the whole script
*
* @test
- * @run
+ * @run
*/
function template() {
diff --git a/test/script/basic/NASHORN-705.js b/test/script/basic/NASHORN-705.js
index a65ef843..de84c4b4 100644
--- a/test/script/basic/NASHORN-705.js
+++ b/test/script/basic/NASHORN-705.js
@@ -2,21 +2,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-71.js b/test/script/basic/NASHORN-71.js
index 913ff76d..5daf3596 100644
--- a/test/script/basic/NASHORN-71.js
+++ b/test/script/basic/NASHORN-71.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-710.js b/test/script/basic/NASHORN-710.js
index 83b17782..9aecf600 100644
--- a/test/script/basic/NASHORN-710.js
+++ b/test/script/basic/NASHORN-710.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-711.js b/test/script/basic/NASHORN-711.js
index af6e9c81..ce0cafef 100644
--- a/test/script/basic/NASHORN-711.js
+++ b/test/script/basic/NASHORN-711.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-72.js b/test/script/basic/NASHORN-72.js
index edf0a237..548844ba 100644
--- a/test/script/basic/NASHORN-72.js
+++ b/test/script/basic/NASHORN-72.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-722.js b/test/script/basic/NASHORN-722.js
index e1584ab9..f51d5ddb 100644
--- a/test/script/basic/NASHORN-722.js
+++ b/test/script/basic/NASHORN-722.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-73.js b/test/script/basic/NASHORN-73.js
index 04c96908..d565c1da 100644
--- a/test/script/basic/NASHORN-73.js
+++ b/test/script/basic/NASHORN-73.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -50,8 +50,8 @@ for ( ; ; ) {
while (true) {
break;
- if (true) {
- var s;
+ if (true) {
+ var s;
}
}
@@ -61,20 +61,20 @@ print("u = "+u);
for ( ; ; ) {
break;
while (true) {
- do {
- var u;
- } while (true);
- }
+ do {
+ var u;
+ } while (true);
+ }
}
function terminal() {
print("r = "+r);
print("t = "+t);
for (;;) {
- var r;
- return;
- var t;
- print("THIS SHOULD NEVER BE PRINTED!");
+ var r;
+ return;
+ var t;
+ print("THIS SHOULD NEVER BE PRINTED!");
}
print("NEITHER SHOULD THIS");
}
@@ -84,13 +84,13 @@ terminal();
function terminal2() {
print("q = "+q);
for (;;) {
- return;
- print("THIS SHOULD NEVER BE PRINTED!");
+ return;
+ print("THIS SHOULD NEVER BE PRINTED!");
}
print("NEITHER SHOULD THIS");
}
-try {
+try {
terminal2();
} catch (e) {
print(e);
@@ -108,13 +108,13 @@ try {
} catch (e) {
print(e);
}
-
+
function disp_a() {
var a = 20;
print("Value of 'a' inside the function " + a);
}
-
+
var a = 10;
disp_a();
diff --git a/test/script/basic/NASHORN-737.js b/test/script/basic/NASHORN-737.js
index 3db48918..146da9dc 100644
--- a/test/script/basic/NASHORN-737.js
+++ b/test/script/basic/NASHORN-737.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-737.js.EXPECTED b/test/script/basic/NASHORN-737.js.EXPECTED
index 77c79657..3a33d9fe 100644
--- a/test/script/basic/NASHORN-737.js.EXPECTED
+++ b/test/script/basic/NASHORN-737.js.EXPECTED
@@ -3,10 +3,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "label"
- },
+ "label": "label",
"body": {
"type": "BlockStatement",
"body": [
@@ -21,10 +18,7 @@
"body": [
{
"type": "BreakStatement",
- "label": {
- "type": "Identifier",
- "name": "label"
- }
+ "label": "label"
}
]
}
diff --git a/test/script/basic/NASHORN-74.js b/test/script/basic/NASHORN-74.js
index 1d44e067..9a384ac0 100644
--- a/test/script/basic/NASHORN-74.js
+++ b/test/script/basic/NASHORN-74.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-740.js b/test/script/basic/NASHORN-740.js
index 553efdda..589777ba 100644
--- a/test/script/basic/NASHORN-740.js
+++ b/test/script/basic/NASHORN-740.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-75.js b/test/script/basic/NASHORN-75.js
index ebcd782c..8e446ff6 100644
--- a/test/script/basic/NASHORN-75.js
+++ b/test/script/basic/NASHORN-75.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-758.js b/test/script/basic/NASHORN-758.js
index f57eaf19..2942161d 100644
--- a/test/script/basic/NASHORN-758.js
+++ b/test/script/basic/NASHORN-758.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-759.js b/test/script/basic/NASHORN-759.js
index 09d2b3e3..41c59744 100644
--- a/test/script/basic/NASHORN-759.js
+++ b/test/script/basic/NASHORN-759.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-760.js b/test/script/basic/NASHORN-760.js
index 1974ddef..d8492b76 100644
--- a/test/script/basic/NASHORN-760.js
+++ b/test/script/basic/NASHORN-760.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,8 +29,8 @@
*/
// problem 1
// the conversions in TernaryNode are not necessary, but they should not cause problems. They did
-// this was because the result of Global.allocate(Object[])Object which returns a NativeObject.
-// was tracked as an object type on our stack. The type system did not recognize this as an array.
+// this was because the result of Global.allocate(Object[])Object which returns a NativeObject.
+// was tracked as an object type on our stack. The type system did not recognize this as an array.
// Then the explicit conversions became "convert NativeArray->Object[]" which is a checkccast Object[]
// which naturally failed.
diff --git a/test/script/basic/NASHORN-768.js b/test/script/basic/NASHORN-768.js
index 5723d6d1..a3bea4f7 100644
--- a/test/script/basic/NASHORN-768.js
+++ b/test/script/basic/NASHORN-768.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -46,7 +46,7 @@ var id = "engine-global-id";
// global object
var obj = {
foo: 42,
- bar: function(x) {
+ bar: function(x) {
if (id != "engine-global-id") {
throw "id != 'engine-global-id'";
}
diff --git a/test/script/basic/NASHORN-778.js b/test/script/basic/NASHORN-778.js
index b165882d..654a8771 100644
--- a/test/script/basic/NASHORN-778.js
+++ b/test/script/basic/NASHORN-778.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-78.js b/test/script/basic/NASHORN-78.js
index 549164dc..3f6ff089 100644
--- a/test/script/basic/NASHORN-78.js
+++ b/test/script/basic/NASHORN-78.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-79.js b/test/script/basic/NASHORN-79.js
index d6f1e059..d2893b36 100644
--- a/test/script/basic/NASHORN-79.js
+++ b/test/script/basic/NASHORN-79.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,8 +32,8 @@
print((function f(a) {
return a == 0? 1 : a*f(a-1);
})(4));
-
-
+
+
print((function g(a) {
function g(a) { return 1000; }
return a == 0? 1 : a*g(a-1);
diff --git a/test/script/basic/NASHORN-792.js b/test/script/basic/NASHORN-792.js
index 3ba0102d..3b387779 100644
--- a/test/script/basic/NASHORN-792.js
+++ b/test/script/basic/NASHORN-792.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-80.js b/test/script/basic/NASHORN-80.js
index aeb496ff..e6505c4d 100644
--- a/test/script/basic/NASHORN-80.js
+++ b/test/script/basic/NASHORN-80.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-81.js b/test/script/basic/NASHORN-81.js
index 44cda684..e0b9bdfb 100644
--- a/test/script/basic/NASHORN-81.js
+++ b/test/script/basic/NASHORN-81.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-833.js b/test/script/basic/NASHORN-833.js
index b3d0d312..dc25d2df 100644
--- a/test/script/basic/NASHORN-833.js
+++ b/test/script/basic/NASHORN-833.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-837.js b/test/script/basic/NASHORN-837.js
index ef9ec64d..9991270c 100644
--- a/test/script/basic/NASHORN-837.js
+++ b/test/script/basic/NASHORN-837.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-85.js b/test/script/basic/NASHORN-85.js
index bdad20f4..3d6d3e83 100644
--- a/test/script/basic/NASHORN-85.js
+++ b/test/script/basic/NASHORN-85.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-86.js b/test/script/basic/NASHORN-86.js
index 07237262..67711d51 100644
--- a/test/script/basic/NASHORN-86.js
+++ b/test/script/basic/NASHORN-86.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-87.js b/test/script/basic/NASHORN-87.js
index 2283dcd3..63896b71 100644
--- a/test/script/basic/NASHORN-87.js
+++ b/test/script/basic/NASHORN-87.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-89.js b/test/script/basic/NASHORN-89.js
index 54912392..470d5b0d 100644
--- a/test/script/basic/NASHORN-89.js
+++ b/test/script/basic/NASHORN-89.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-90.js b/test/script/basic/NASHORN-90.js
index 99c2a4ae..3fc37297 100644
--- a/test/script/basic/NASHORN-90.js
+++ b/test/script/basic/NASHORN-90.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-91.js b/test/script/basic/NASHORN-91.js
index 1e1df61e..4aab313e 100644
--- a/test/script/basic/NASHORN-91.js
+++ b/test/script/basic/NASHORN-91.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-92.js b/test/script/basic/NASHORN-92.js
index a05997f3..715505a0 100644
--- a/test/script/basic/NASHORN-92.js
+++ b/test/script/basic/NASHORN-92.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-93.js b/test/script/basic/NASHORN-93.js
index c4247288..ba4c0561 100644
--- a/test/script/basic/NASHORN-93.js
+++ b/test/script/basic/NASHORN-93.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-95.js b/test/script/basic/NASHORN-95.js
index 38d7285e..2ba94034 100644
--- a/test/script/basic/NASHORN-95.js
+++ b/test/script/basic/NASHORN-95.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-96.js b/test/script/basic/NASHORN-96.js
index 451b0188..159e2b2b 100644
--- a/test/script/basic/NASHORN-96.js
+++ b/test/script/basic/NASHORN-96.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-97.js b/test/script/basic/NASHORN-97.js
index 0f7128a5..d103ff54 100644
--- a/test/script/basic/NASHORN-97.js
+++ b/test/script/basic/NASHORN-97.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/NASHORN-98.js b/test/script/basic/NASHORN-98.js
index 9e341e0c..9c23c08c 100644
--- a/test/script/basic/NASHORN-98.js
+++ b/test/script/basic/NASHORN-98.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -35,7 +35,7 @@ try {
fail("syntax error expected here got " + e);
}
printError(e);
-}
+}
try {
eval("var x = { foo: 33 bar: 'hello' }");
@@ -44,4 +44,4 @@ try {
fail("syntax error expected here got " + e);
}
printError(e);
-}
+}
diff --git a/test/script/basic/NASHORN-99.js b/test/script/basic/NASHORN-99.js
index eaf717a5..7c14e4ea 100644
--- a/test/script/basic/NASHORN-99.js
+++ b/test/script/basic/NASHORN-99.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/access-specializer.js b/test/script/basic/access-specializer.js
index d60260a9..7163318b 100644
--- a/test/script/basic/access-specializer.js
+++ b/test/script/basic/access-specializer.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,9 +24,9 @@
/**
* This is a simple test that checks that access specialization in FinalizeTypes is consistent.
* Here, a2 = 0 will be turned int {I}a2 = 0, and all would be fine and well, only we can't change
- * the symbol type for a2 from double, and we can't as it's not a temporary. Either we have to put
+ * the symbol type for a2 from double, and we can't as it's not a temporary. Either we have to put
* a temporary in at the late finalize stage and add another assignment, or we genericize the check
- * in CodeGenerator#Store so we detect whether a target is of the wrong type before storing. It
+ * in CodeGenerator#Store so we detect whether a target is of the wrong type before storing. It
* is hopefully very rare, and will only be a problem when assignment results that have been
* specialized live on the stack
*
diff --git a/test/script/basic/addition.js b/test/script/basic/addition.js
index 6f8d099e..31ea6f28 100644
--- a/test/script/basic/addition.js
+++ b/test/script/basic/addition.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/allgettersetters.js b/test/script/basic/allgettersetters.js
index 1cb95623..c6e34256 100644
--- a/test/script/basic/allgettersetters.js
+++ b/test/script/basic/allgettersetters.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/andor.js b/test/script/basic/andor.js
index 7d65ee18..9a1ff8b6 100644
--- a/test/script/basic/andor.js
+++ b/test/script/basic/andor.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* and or test.
*
* @test
- * @run
+ * @run
*/
print("a" && "b");
diff --git a/test/script/basic/anonrecur.js b/test/script/basic/anonrecur.js
index 393a2ac8..3f5dd71a 100644
--- a/test/script/basic/anonrecur.js
+++ b/test/script/basic/anonrecur.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/apply_to_call/apply_to_call1.js b/test/script/basic/apply_to_call/apply_to_call1.js
new file mode 100644
index 00000000..74ebb2ff
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call1.js
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call1.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test() {
+ x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting apply now");
+
+x.initialize = {
+ apply : function() {
+ for (var i=0;i<arguments.length;i++) {
+ print("I am not who you think " + arguments[i]);
+ }
+ x.a = arguments[1][0];
+ }
+};
+
+test(4712);
+print(x.a);
diff --git a/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED
new file mode 100644
index 00000000..1d2a6557
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting apply now
+I am not who you think [object Object]
+I am not who you think [object Arguments]
+4712
diff --git a/test/script/basic/apply_to_call/apply_to_call2.js b/test/script/basic/apply_to_call/apply_to_call2.js
new file mode 100644
index 00000000..7356f2c9
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call2.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call2.js - do one apply to call specialization, then override call and make sure it reverts (i.e. stops
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test() {
+ x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting call now");
+
+Function.prototype.call = function() {
+ throw "this should never be thrown - test should revert to builtin apply";
+};
+
+test(1,2,3);
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED
new file mode 100644
index 00000000..651fbb4f
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting call now
+1
+2
+3
diff --git a/test/script/basic/apply_to_call/apply_to_call3.js b/test/script/basic/apply_to_call/apply_to_call3.js
new file mode 100644
index 00000000..f08c91b8
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call3.js
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call3.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops
+ * calling call). Then apply should break and throw exception
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test() {
+ x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting apply now");
+
+Function.prototype.apply = function() {
+ throw "This should be thrown, as the test call transform is no longer valid";
+};
+
+try {
+ test(1,2,3);
+} catch (e) {
+ print(e);
+}
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED
new file mode 100644
index 00000000..b1007bd7
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED
@@ -0,0 +1,9 @@
+start
+4711
+23
+17
+Overwriting apply now
+This should be thrown, as the test call transform is no longer valid
+4711
+23
+17
diff --git a/test/script/basic/apply_to_call/apply_to_call4.js b/test/script/basic/apply_to_call/apply_to_call4.js
new file mode 100644
index 00000000..27067cc2
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call4.js
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call4.js - various escaping args patterns that prevent the optimization from being applied
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function f(x) {
+ print("this is a black hole - arguments escape");
+}
+
+function test() {
+ f(arguments);
+ x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test2() {
+ arguments[0] = 17;
+ x.initialize.apply(x, arguments);
+}
+
+test2(1,2,3);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test3() {
+ var escape = arguments[0];
+ f(escape);
+ x.initialize.apply(x, arguments);
+}
+
+test3("alpha", "beta", "gamma");
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test4() {
+ var escape = arguments.length;
+ f(escape);
+ x.initialize.apply(x, arguments);
+}
+
+test4(1.2, 2.3, 3.4);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test5() {
+ x.initialize.apply(x, arguments, 17);
+}
+
+print("test 5 done");
+test5(11, 22);
+print("a="+typeof(x.a));
+print(x.b);
+print(x.c);
+
+print("Now it's time for transforms");
+
+function test6() {
+ x.initialize.apply(x, arguments);
+}
+
+test6(19, 20, 21);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test7() {
+ x.initialize.apply(x, arguments);
+}
+
+test7(1, 2.2, 17, 18);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Should have transformed");
+
+function test8() {
+ var apply = f;
+ x.initialize.apply(x, arguments);
+}
+
+test8(7,8,9);
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED
new file mode 100644
index 00000000..41ad10b6
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED
@@ -0,0 +1,31 @@
+start
+this is a black hole - arguments escape
+4711
+23
+17
+17
+2
+3
+this is a black hole - arguments escape
+alpha
+beta
+gamma
+this is a black hole - arguments escape
+1.2
+2.3
+3.4
+test 5 done
+a=number
+22
+undefined
+Now it's time for transforms
+19
+20
+21
+1
+2.2
+17
+Should have transformed
+7
+8
+9
diff --git a/test/script/basic/apply_to_call/apply_to_call5.js b/test/script/basic/apply_to_call/apply_to_call5.js
new file mode 100644
index 00000000..adb9401e
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call5.js
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call5.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test() {
+ x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting apply now");
+x.initialize.apply = function() { print("New function for apply - not a property"); }
+
+test(4712);
+print(x.a);
+
+
+var x2 = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test2() {
+ x2.initialize.apply(x2, arguments);
+}
+
+test2(4711,23,17);
+print(x2.a);
+print(x2.b);
+print(x2.c);
+
+print("Overwriting apply now");
+x2.initialize['apply'] = function() { print("New function for apply - not a property"); }
+
+test(4712);
+print(x2.a);
+
+var x3 = {
+ a : 0,
+ b : 0,
+ c : 0,
+ initialize : function(x,y,z) {
+ this.a = x;
+ this.b = y;
+ this.c = z;
+ }
+};
+
+function test3() {
+ x3.initialize.apply(x3, arguments);
+}
+
+test3(4711,23,17);
+print(x3.a);
+print(x3.b);
+print(x3.c);
+
+print("Overwriting apply now");
+eval("x3.initialize['apply'] = function() { print('New function for apply - not a property'); }");
+
+test(4712);
+print(x3.a);
diff --git a/test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED
new file mode 100644
index 00000000..4d678e90
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call5.js.EXPECTED
@@ -0,0 +1,19 @@
+start
+4711
+23
+17
+Overwriting apply now
+New function for apply - not a property
+4711
+4711
+23
+17
+Overwriting apply now
+New function for apply - not a property
+4711
+4711
+23
+17
+Overwriting apply now
+New function for apply - not a property
+4711
diff --git a/test/script/basic/apply_to_call/apply_to_call_recompile.js b/test/script/basic/apply_to_call/apply_to_call_recompile.js
new file mode 100644
index 00000000..29c44a6f
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call_recompile.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_recompile.js - make sure that recompilations of methods are
+ * transform equivalent when it comes to apply2call, or we will have
+ * erroneous contiunation info generation
+ *
+ * @test
+ * @run
+ */
+
+function K() {
+ K.b2BoundValues.apply(this, arguments);
+ this.constructor === K && K.b2BoundValues.apply(this, arguments)
+}
+
+K.b2BoundValues = function(a,b,c) {
+ print(a);
+ print(b);
+ print(c);
+};
+
+new K(11,12,13,14,15,16);
diff --git a/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED
new file mode 100644
index 00000000..44d695b9
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED
@@ -0,0 +1,6 @@
+11
+12
+13
+11
+12
+13
diff --git a/test/script/basic/apply_to_call/apply_to_call_varargs.js b/test/script/basic/apply_to_call/apply_to_call_varargs.js
new file mode 100644
index 00000000..4d629f69
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call_varargs.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * apply_to_call_varars - make sure that apply to call transform works
+ * even when supplying too few arguments
+ *
+ * @test
+ * @run
+ */
+
+var Class = {
+ create: function() {
+ return function() { //vararg
+ this.initialize.apply(this, arguments);
+ }
+ }
+};
+
+Color = Class.create();
+Color.prototype = {
+ red: 0, green: 0, blue: 0,
+ initialize: function(r) {
+ this.red = r;
+ this.green = 255;
+ this.blue = 255;
+ },
+ toString: function() {
+ print("[red=" + this.red + ", green=" + this.green + ", blue=" + this.blue + "]");
+ }
+};
+
+var colors = new Array(16);
+function run() {
+ for (var i = 0; i < colors.length; i++) {
+ colors[i&0xf] = (new Color(i));
+ }
+}
+
+run();
+for (var i = 0; i < colors.length; i++) {
+ print(colors[i]);
+}
+
+print("Swapping out call");
+Function.prototype.call = function() {
+ throw "This should not happen, apply should be called instead";
+};
+
+run();
+for (var i = 0; i < colors.length; i++) {
+ print(colors[i]);
+}
+
+print("All done!");
diff --git a/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED b/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED
new file mode 100644
index 00000000..d8f338bd
--- /dev/null
+++ b/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED
@@ -0,0 +1,66 @@
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+Swapping out call
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+All done!
diff --git a/test/script/basic/applycall.js b/test/script/basic/applycall.js
index 6756eadb..b49cfd52 100644
--- a/test/script/basic/applycall.js
+++ b/test/script/basic/applycall.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/args.js b/test/script/basic/args.js
index 7b8ff0a1..3d4451c0 100644
--- a/test/script/basic/args.js
+++ b/test/script/basic/args.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/arity.js b/test/script/basic/arity.js
index b53b298d..554961ec 100644
--- a/test/script/basic/arity.js
+++ b/test/script/basic/arity.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* arity test.
*
* @test
- * @run
+ * @run
*/
function func1(a) { print(a); }
diff --git a/test/script/basic/arrayprotoclass.js b/test/script/basic/arrayprotoclass.js
index f5993c05..bc7a56c4 100644
--- a/test/script/basic/arrayprotoclass.js
+++ b/test/script/basic/arrayprotoclass.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/arrays.js b/test/script/basic/arrays.js
index 6cab3754..03ad4312 100644
--- a/test/script/basic/arrays.js
+++ b/test/script/basic/arrays.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -155,6 +155,6 @@ print(Array.prototype.map.call("hello", function() {}));
print(Array.prototype.reduce.call("hello", function() {}));
print(Array.prototype.toString.call(new java.lang.Object()));
print(Array.prototype.toLocaleString.call(new java.lang.Object()));
-print(Array.prototype.reduceRight.call(new java.lang.Object(),
+print(Array.prototype.reduceRight.call(new java.lang.Object(),
function() {}, 33));
diff --git a/test/script/basic/arrays2.js b/test/script/basic/arrays2.js
index 1342c175..8856dab6 100644
--- a/test/script/basic/arrays2.js
+++ b/test/script/basic/arrays2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/arraysIntKey.js b/test/script/basic/arrays_int_key.js
index c9182efd..0ba18d2d 100644
--- a/test/script/basic/arraysIntKey.js
+++ b/test/script/basic/arrays_int_key.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
var o = [0];
Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
diff --git a/test/script/basic/arraysIntKey.js.EXPECTED b/test/script/basic/arrays_int_key.js.EXPECTED
index 2edebd4a..2edebd4a 100644
--- a/test/script/basic/arraysIntKey.js.EXPECTED
+++ b/test/script/basic/arrays_int_key.js.EXPECTED
diff --git a/test/script/basic/arrayset.js b/test/script/basic/arrayset.js
index 2fbd2bc4..1f2fd527 100644
--- a/test/script/basic/arrayset.js
+++ b/test/script/basic/arrayset.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-var arr = [];
+var arr = [];
print(arr.length);
print(arr.hasOwnProperty(10000));
print(arr.hasOwnProperty(10));
diff --git a/test/script/basic/arrayundefined.js b/test/script/basic/arrayundefined.js
index 3866c854..5cf24633 100644
--- a/test/script/basic/arrayundefined.js
+++ b/test/script/basic/arrayundefined.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/assign.js b/test/script/basic/assign.js
index abcc5045..04a96257 100644
--- a/test/script/basic/assign.js
+++ b/test/script/basic/assign.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Assign test.
*
* @test
- * @run
+ * @run
*/
var x = 10;
diff --git a/test/script/basic/bitwise_and.js b/test/script/basic/bitwise_and.js
index 32583d43..716fa90e 100644
--- a/test/script/basic/bitwise_and.js
+++ b/test/script/basic/bitwise_and.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/boolean_arithmetic.js b/test/script/basic/boolean_arithmetic.js
new file mode 100644
index 00000000..88110407
--- /dev/null
+++ b/test/script/basic/boolean_arithmetic.js
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * test arithmetic operations on boolean variables
+ *
+ * @test
+ * @run
+ */
+
+function printOp(text, value) {
+ print(text + value);
+}
+
+(function () {
+var t = true;
+var f = false;
+
+print("+")
+printOp("f, f: ", (f + f))
+printOp("f, t: ", (f + t))
+printOp("t, f: ", (t + f))
+printOp("t, t: ", (t + t))
+
+print("-")
+printOp("f, f: ", (f - f))
+printOp("f, t: ", (f - t))
+printOp("t, f: ", (t - f))
+printOp("t, t: ", (t - t))
+
+print("*")
+printOp("f, f: ", (f * f))
+printOp("f, t: ", (f * t))
+printOp("t, f: ", (t * f))
+printOp("t, t: ", (t * t))
+
+print("/")
+printOp("f, f: ", (f / f))
+printOp("f, t: ", (f / t))
+printOp("t, f: ", (t / f))
+printOp("t, t: ", (t / t))
+
+print("<<")
+printOp("f, f: ", (f << f))
+printOp("f, t: ", (f << t))
+printOp("t, f: ", (t << f))
+printOp("t, t: ", (t << t))
+
+print(">>")
+printOp("f, f: ", (f >> f))
+printOp("f, t: ", (f >> t))
+printOp("t, f: ", (t >> f))
+printOp("t, t: ", (t >> t))
+
+print(">>>")
+printOp("f, f: ", (f >>> f))
+printOp("f, t: ", (f >>> t))
+printOp("t, f: ", (t >>> f))
+printOp("t, t: ", (t >>> t))
+
+print("|")
+printOp("f, f: ", (f | f))
+printOp("f, t: ", (f | t))
+printOp("t, f: ", (t | f))
+printOp("t, t: ", (t | t))
+
+print("&")
+printOp("f, f: ", (f & f))
+printOp("f, t: ", (f & t))
+printOp("t, f: ", (t & f))
+printOp("t, t: ", (t & t))
+
+print("^")
+printOp("f, f: ", (f ^ f))
+printOp("f, t: ", (f ^ t))
+printOp("t, f: ", (t ^ f))
+printOp("t, t: ", (t ^ t))
+
+print("~")
+printOp("f: ", (~f))
+printOp("t: ", (~t))
+
+print("+")
+printOp("f: ", (+f))
+printOp("t: ", (+t))
+
+print("-")
+printOp("f: ", (-f))
+printOp("t: ", (-t))
+
+printOp("1/-f: ", (1/-f))
+
+})();
diff --git a/test/script/basic/boolean_arithmetic.js.EXPECTED b/test/script/basic/boolean_arithmetic.js.EXPECTED
new file mode 100644
index 00000000..7020ac3a
--- /dev/null
+++ b/test/script/basic/boolean_arithmetic.js.EXPECTED
@@ -0,0 +1,60 @@
++
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 2
+-
+f, f: 0
+f, t: -1
+t, f: 1
+t, t: 0
+*
+f, f: 0
+f, t: 0
+t, f: 0
+t, t: 1
+/
+f, f: NaN
+f, t: 0
+t, f: Infinity
+t, t: 1
+<<
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 2
+>>
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 0
+>>>
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 0
+|
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 1
+&
+f, f: 0
+f, t: 0
+t, f: 0
+t, t: 1
+^
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 0
+~
+f: -1
+t: -2
++
+f: 0
+t: 1
+-
+f: 0
+t: -1
+1/-f: -Infinity
diff --git a/test/script/basic/booleangetter.js b/test/script/basic/booleangetter.js
index 3f16b74d..237edbe7 100644
--- a/test/script/basic/booleangetter.js
+++ b/test/script/basic/booleangetter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/builtin.js b/test/script/basic/builtin.js
index 4d48bffb..5693c852 100644
--- a/test/script/basic/builtin.js
+++ b/test/script/basic/builtin.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/builtin_assign.js b/test/script/basic/builtin_assign.js
index 7520cb74..02a95440 100644
--- a/test/script/basic/builtin_assign.js
+++ b/test/script/basic/builtin_assign.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/builtinchain.js b/test/script/basic/builtinchain.js
index a5e672e1..05011b7d 100644
--- a/test/script/basic/builtinchain.js
+++ b/test/script/basic/builtinchain.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/calllink.js b/test/script/basic/calllink.js
index 06e546c4..0d27ba9f 100644
--- a/test/script/basic/calllink.js
+++ b/test/script/basic/calllink.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -60,7 +60,7 @@ MyConstructor.prototype.func = function() {
var obj5 = new MyConstructor();
var obj6 = new MyConstructor();
-var arr = [ obj1, obj2, obj3, obj4, obj5, obj6,
+var arr = [ obj1, obj2, obj3, obj4, obj5, obj6,
obj1, obj2, obj3, obj4, obj5, obj6 ];
var myObj;
@@ -69,8 +69,8 @@ for (i in arr) {
obj3.func = function() {
print("new obj3.func called");
}
- obj4.func = function() {
- print("new obj4.func called");
+ obj4.func = function() {
+ print("new obj4.func called");
}
MyConstructor.prototype.func = function() {
print("all new MyConstructor.prototype.func");
diff --git a/test/script/basic/classloader.js b/test/script/basic/classloader.js
index 76764960..b46d23e4 100644
--- a/test/script/basic/classloader.js
+++ b/test/script/basic/classloader.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/closure.js b/test/script/basic/closure.js
index f601375e..30af72ff 100644
--- a/test/script/basic/closure.js
+++ b/test/script/basic/closure.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,14 +25,14 @@
* Closure test.
*
* @test
- * @run
+ * @run
*/
-
+
(function test1(a, b){ print(a, b); })(10, 20);
(function test2(a, b){ print(a, b); })(10);
(function test3(a, b){ print(a, b); })(10, 20, 30);
-(function test4(a, b){
- print(arguments[0] + "," + arguments[1]);
+(function test4(a, b){
+ print(arguments[0] + "," + arguments[1]);
print(arguments.callee);
})(10, 20);
diff --git a/test/script/basic/closure.js.EXPECTED b/test/script/basic/closure.js.EXPECTED
index d039115f..e6b807f8 100644
--- a/test/script/basic/closure.js.EXPECTED
+++ b/test/script/basic/closure.js.EXPECTED
@@ -2,7 +2,7 @@
10 undefined
10 20
10,20
-function test4(a, b){
- print(arguments[0] + "," + arguments[1]);
+function test4(a, b){
+ print(arguments[0] + "," + arguments[1]);
print(arguments.callee);
}
diff --git a/test/script/basic/commandargs.js b/test/script/basic/commandargs.js
index 733b6792..ac28a43a 100644
--- a/test/script/basic/commandargs.js
+++ b/test/script/basic/commandargs.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Simple test to check command line arguments for scripts.
*
* @test
- * @argument hello
+ * @argument hello
* @argument world
* @run
*/
@@ -33,4 +33,4 @@
for (i in arguments) {
print(arguments[i]);
}
-
+
diff --git a/test/script/basic/compile-octane-normal.js b/test/script/basic/compile-octane-normal.js
new file mode 100644
index 00000000..c671d572
--- /dev/null
+++ b/test/script/basic/compile-octane-normal.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
+ * @test
+ * @fork
+ * @runif external.octane
+ * @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
+ */
+
+var fn = __DIR__ + 'compile-octane.js';
+var url = new java.io.File(fn).toURL();
+loadWithNewGlobal(url);
diff --git a/test/script/basic/compile-octane-normal.js.EXPECTED b/test/script/basic/compile-octane-normal.js.EXPECTED
new file mode 100644
index 00000000..5577bcca
--- /dev/null
+++ b/test/script/basic/compile-octane-normal.js.EXPECTED
@@ -0,0 +1,30 @@
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
diff --git a/test/script/basic/compile-octane-splitter.js b/test/script/basic/compile-octane-splitter.js
index 497b5ab7..58c5966a 100644
--- a/test/script/basic/compile-octane-splitter.js
+++ b/test/script/basic/compile-octane-splitter.js
@@ -1,32 +1,44 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
* @test
+ * @fork
* @option -Dnashorn.compiler.splitter.threshold=1000
* @fork
* @runif external.octane
- */
+ * @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
+ */
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+var fn = __DIR__ + 'compile-octane.js';
+var url = new java.io.File(fn).toURL();
+loadWithNewGlobal(url);
diff --git a/test/script/basic/compile-octane-splitter.js.EXPECTED b/test/script/basic/compile-octane-splitter.js.EXPECTED
index 9e4920dc..5577bcca 100644
--- a/test/script/basic/compile-octane-splitter.js.EXPECTED
+++ b/test/script/basic/compile-octane-splitter.js.EXPECTED
@@ -1,14 +1,30 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
diff --git a/test/script/basic/compile-octane.js b/test/script/basic/compile-octane.js
index da40d5ea..b37038f9 100644
--- a/test/script/basic/compile-octane.js
+++ b/test/script/basic/compile-octane.js
@@ -1,30 +1,143 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * @test
- * @runif external.octane
- */
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
+ * This means that if you use this subtest as a compilation test
+ * harness, pass the arguments:
+ *
+ * -scripting -Dnashorn.typeInfo.disabled=true --class-cache-size=0
+ * --persistent-code-cache=false
+ *
+ * @subtest
+ */
+
+load(__DIR__ + 'octane-payload.js');
+
+var DEFAULT_ITERS = 1; //default is one iteration through each benchmark
+var iters = DEFAULT_ITERS;
+var args = [];
+
+if (typeof $ARGS !== 'undefined') {
+ args = $ARGS;
+} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
+ args = arguments;
+}
+
+var onlyTheseTests = [];
+var verbose = false;
+
+for (var i = 0; i < args.length; ) {
+ var arg = args[i];
+ if (arg === '--iterations') {
+ iters = +args[++i];
+ } else if (arg === '--verbose') {
+ verbose = true;
+ } else {
+ onlyTheseTests.push(arg);
+ }
+ i++;
+}
+
+if (isNaN(iters)) {
+ iters = DEFAULT_ITERS;
+}
+
+if (iters != DEFAULT_ITERS) {
+ print("Running " + iters + " iterations of each compilation.");
+}
+
+function print_if_verbose(x) {
+ if (verbose) {
+ print(x);
+ }
+}
+
+function contains(a, obj) {
+ for (var i = 0; i < a.length; i++) {
+ if (a[i] === obj) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var testsCompiled = [];
+
+for (var j in tests) {
+ var test_name = tests[j].name;
+ var files = tests[j].files;
+
+ if (onlyTheseTests.length > 0 && !contains(onlyTheseTests, test_name)) {
+ print_if_verbose("Skipping " + test_name);
+ continue;
+ }
+
+ if (!contains(testsCompiled, test_name)) {
+ testsCompiled.push(test_name);
+ }
+
+ var str = "Compiling '" + test_name + "'...";
+ if (files.length > 1) {
+ str += " (" + files.length + " files)";
+ }
+ if (iters != 1) {
+ str += " (" + iters + " times)";
+ }
+ str + "...";
+ print(str);
+
+ for (var iteration = 0; iteration < iters; iteration++) {
+
+ //get a new global to avoid symbol pollution and reloads of base
+ //in the same namespace
+ var newGlobal = loadWithNewGlobal({script:'this', name:'test'});
+
+ //load base into the new global so we get BenchmarkSuite etc
+ newGlobal.load(base);
+
+ //load all files in the single benchmark
+ for (var k in files) {
+ var file = files[k];
+ if (iteration >= 0) { //only display message on first iteration
+ var str2 = "\t";
+ if (iters > 1) {
+ str2 += " [iteration " + (iteration + 1) + "]";
+ }
+ str2 += " processing file: " + file + "...";
+ print_if_verbose(str2);
+ }
+ newGlobal.load(new java.io.File(path + file).toURL());
+ }
+ }
+ print("Done.");
+}
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+if (testsCompiled.length == 0) {
+ print("Error: no tests given to compile");
+}
diff --git a/test/script/basic/compile-octane.js.EXPECTED b/test/script/basic/compile-octane.js.EXPECTED
deleted file mode 100644
index 9e4920dc..00000000
--- a/test/script/basic/compile-octane.js.EXPECTED
+++ /dev/null
@@ -1,14 +0,0 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
diff --git a/test/script/basic/condassign.js b/test/script/basic/condassign.js
index a70f5a40..6b5d6ff0 100644
--- a/test/script/basic/condassign.js
+++ b/test/script/basic/condassign.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/construct.js b/test/script/basic/construct.js
index 66e3d419..2a268ed6 100644
--- a/test/script/basic/construct.js
+++ b/test/script/basic/construct.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,19 +25,19 @@
* Constructor test.
*
* @test
- * @run
+ * @run
*/
function Test() {
this.A = "A big fat string";
this.B = 123;
-
+
this.F = function(x) { return x; }
-
- var proto = Object.getPrototypeOf(this);
+
+ var proto = Object.getPrototypeOf(this);
proto.R = "A big fat string";
proto.S = 123;
-
+
proto.T = function(x) { return x; }
return "monkey";
diff --git a/test/script/basic/constructorname.js b/test/script/basic/constructorname.js
index 16e3aec0..ee3e25f8 100644
--- a/test/script/basic/constructorname.js
+++ b/test/script/basic/constructorname.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/convert.js b/test/script/basic/convert.js
index 8d11d122..2c87661c 100644
--- a/test/script/basic/convert.js
+++ b/test/script/basic/convert.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -42,7 +42,7 @@ print(list);
// object to Map
obj = { foo: 333, bar: 'hello'};
-var map = ScriptUtils.convert(obj, java.util.Map.class);
+var map = ScriptUtils.wrap(obj);
print(map instanceof java.util.Map);
for (m in map) {
print(m + " " + map[m]);
diff --git a/test/script/basic/dataview_endian.js b/test/script/basic/dataview_endian.js
index f7607c0e..668167a8 100644
--- a/test/script/basic/dataview_endian.js
+++ b/test/script/basic/dataview_endian.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/dataview_getset.js b/test/script/basic/dataview_getset.js
index 8c7a994c..97fc1f4b 100644
--- a/test/script/basic/dataview_getset.js
+++ b/test/script/basic/dataview_getset.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/dataview_new.js b/test/script/basic/dataview_new.js
index 78f8183d..54ebc9f0 100644
--- a/test/script/basic/dataview_new.js
+++ b/test/script/basic/dataview_new.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -57,7 +57,8 @@ function checkError(callback, ErrorType) {
fail("Should have thrown " + ErrorType.name);
} catch (e) {
if (! (e instanceof ErrorType)) {
- fail("Expected " + ErrorType.name + " got " + e);
+ print("Expected " + ErrorType.name + " got " + e);
+ e.printStackTrace()
}
}
}
diff --git a/test/script/basic/date.js b/test/script/basic/date.js
index ea770894..22a38db3 100644
--- a/test/script/basic/date.js
+++ b/test/script/basic/date.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/dateparse.js b/test/script/basic/dateparse.js
index 919a681c..fe29d4b9 100644
--- a/test/script/basic/dateparse.js
+++ b/test/script/basic/dateparse.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/decinc.js b/test/script/basic/decinc.js
index 3ee1ac14..b77c624d 100644
--- a/test/script/basic/decinc.js
+++ b/test/script/basic/decinc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/delete.js b/test/script/basic/delete.js
index 6d7f8846..ea700130 100644
--- a/test/script/basic/delete.js
+++ b/test/script/basic/delete.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/delete2.js b/test/script/basic/delete2.js
index 3d148474..1ca48a88 100644
--- a/test/script/basic/delete2.js
+++ b/test/script/basic/delete2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,7 +26,7 @@
* throws VerifyError!!
*
* @test
- * @run
+ * @run
*/
var a = 10;
@@ -39,7 +39,7 @@ function d() { print("side effect"); }
function e(g) {
var f = 10;
-
+
print(delete f);
print(f);
print(delete g);
diff --git a/test/script/basic/dotpropname.js b/test/script/basic/dotpropname.js
index 03704ec7..6df361ce 100644
--- a/test/script/basic/dotpropname.js
+++ b/test/script/basic/dotpropname.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/doublecache.js b/test/script/basic/doublecache.js
index 91ac8459..c42c8a94 100644
--- a/test/script/basic/doublecache.js
+++ b/test/script/basic/doublecache.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -39,7 +39,7 @@ var x = [
0.5,
100,
200,
-
+
-200,
-100,
-0.5,
@@ -50,5 +50,5 @@ var x = [
100,
200
];
-
+
for (i in x) print(x[i]);
diff --git a/test/script/basic/enumeration.js b/test/script/basic/enumeration.js
index 3746dfe7..7453dcb7 100644
--- a/test/script/basic/enumeration.js
+++ b/test/script/basic/enumeration.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * Make sure that there are no-enumerable items on standard objects.
+ * Make sure that there are no-enumerable items on standard objects.
*
* @test
* @run
diff --git a/test/script/basic/errors.js b/test/script/basic/errors.js
index c698ef8c..ee56d76e 100644
--- a/test/script/basic/errors.js
+++ b/test/script/basic/errors.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Basic checks for Error constructors.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/errorstack.js b/test/script/basic/errorstack.js
index 8fcd25a2..d0e7ea6e 100644
--- a/test/script/basic/errorstack.js
+++ b/test/script/basic/errorstack.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,7 +26,7 @@
*
* @test
* @run
- */
+ */
function func1() {
func2();
diff --git a/test/script/basic/es6/block-function-decl.js b/test/script/basic/es6/block-function-decl.js
new file mode 100644
index 00000000..f69ef84a
--- /dev/null
+++ b/test/script/basic/es6/block-function-decl.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+{
+ // f is defined on block level
+ print(f);
+ f();
+ function f() {
+ print("in f");
+ }
+ print(f);
+ f();
+}
+
+try {
+ print(typeof f);
+ f();
+} catch (e) {
+ print(e);
+}
+
diff --git a/test/script/basic/es6/block-function-decl.js.EXPECTED b/test/script/basic/es6/block-function-decl.js.EXPECTED
new file mode 100644
index 00000000..9bb409c6
--- /dev/null
+++ b/test/script/basic/es6/block-function-decl.js.EXPECTED
@@ -0,0 +1,10 @@
+function f() {
+ print("in f");
+ }
+in f
+function f() {
+ print("in f");
+ }
+in f
+undefined
+ReferenceError: "f" is not defined
diff --git a/test/script/basic/es6/const-empty.js b/test/script/basic/es6/const-empty.js
new file mode 100644
index 00000000..c34d1d51
--- /dev/null
+++ b/test/script/basic/es6/const-empty.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+ eval('"use strict";\n' +
+ 'const x;\n');
+} catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+}
diff --git a/test/script/basic/es6/const-empty.js.EXPECTED b/test/script/basic/es6/const-empty.js.EXPECTED
new file mode 100644
index 00000000..d3684a89
--- /dev/null
+++ b/test/script/basic/es6/const-empty.js.EXPECTED
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/const-empty.js#33:4<eval>:2:7 Missing assignment to constant "x"
+const x;
+ ^
diff --git a/test/script/basic/es6/const-reassign.js b/test/script/basic/es6/const-reassign.js
new file mode 100644
index 00000000..421d5711
--- /dev/null
+++ b/test/script/basic/es6/const-reassign.js
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x = 1;\n');
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x++;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x--;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ '++x;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ '--x;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x += 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x *= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x /= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x %= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x |= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x &= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x ^= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x <<= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x >>= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'x >>>= 1;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'delete x;\n');
+ fail("const assignment didn't throw");
+} catch (e) {
+ print(e.name);
+}
diff --git a/test/script/basic/es6/const-reassign.js.EXPECTED b/test/script/basic/es6/const-reassign.js.EXPECTED
new file mode 100644
index 00000000..e1fa61a2
--- /dev/null
+++ b/test/script/basic/es6/const-reassign.js.EXPECTED
@@ -0,0 +1,16 @@
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
+SyntaxError
diff --git a/test/script/basic/es6/const-redeclare-extra.js b/test/script/basic/es6/const-redeclare-extra.js
new file mode 100644
index 00000000..94fc53b2
--- /dev/null
+++ b/test/script/basic/es6/const-redeclare-extra.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"))
+ }
+}
+
+tryIt(<<CODE
+ "use strict";
+ const x = 2;
+ var x = {};
+CODE)
+
+tryIt(<<CODE
+ "use strict";
+ var x = 2;
+ const x = {};
+CODE)
+
+tryIt(<<CODE
+ "use strict";
+ function x () {}
+ const x = 5;
+CODE)
+
diff --git a/test/script/basic/es6/const-redeclare-extra.js.EXPECTED b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED
new file mode 100644
index 00000000..06af782e
--- /dev/null
+++ b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED
@@ -0,0 +1,9 @@
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
+ var x = {};
+ ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
+ const x = {};
+ ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
+ const x = 5;
+ ^
diff --git a/test/script/basic/es6/const-redeclare.js b/test/script/basic/es6/const-redeclare.js
new file mode 100644
index 00000000..efe34ac2
--- /dev/null
+++ b/test/script/basic/es6/const-redeclare.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+ eval('"use strict";\n' +
+ 'const x = 2;\n' +
+ 'const x = 2;\n');
+} catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+}
diff --git a/test/script/basic/es6/const-redeclare.js.EXPECTED b/test/script/basic/es6/const-redeclare.js.EXPECTED
new file mode 100644
index 00000000..44b6a70f
--- /dev/null
+++ b/test/script/basic/es6/const-redeclare.js.EXPECTED
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/const-redeclare.js#33:4<eval>:2:6 Variable "x" has already been declared
+const x = 2;
+ ^
diff --git a/test/script/basic/es6/const-self.js b/test/script/basic/es6/const-self.js
new file mode 100644
index 00000000..49855ad0
--- /dev/null
+++ b/test/script/basic/es6/const-self.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+const a = 1, b = a;
+
+print(a, b);
+
+try {
+ eval('"use strict";\n' +
+ 'const a = a;\n');
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/es6/const-self.js.EXPECTED b/test/script/basic/es6/const-self.js.EXPECTED
new file mode 100644
index 00000000..6aad2ef1
--- /dev/null
+++ b/test/script/basic/es6/const-self.js.EXPECTED
@@ -0,0 +1,2 @@
+1 1
+ReferenceError: "a" is not defined
diff --git a/test/script/basic/es6/const-tdz.js b/test/script/basic/es6/const-tdz.js
new file mode 100644
index 00000000..a66f0058
--- /dev/null
+++ b/test/script/basic/es6/const-tdz.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+{
+ print("test 1");
+
+ function f() {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ f();
+ const a = 1;
+ f();
+}
+
+{
+ print("test 2");
+
+ function f() {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ f();
+ const a = 2;
+ f();
+}
+
+{
+ print("test 3");
+ {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ const a = 3;
+
+ {
+ print(a);
+ }
+}
+
diff --git a/test/script/basic/es6/const-tdz.js.EXPECTED b/test/script/basic/es6/const-tdz.js.EXPECTED
new file mode 100644
index 00000000..4f3c58c8
--- /dev/null
+++ b/test/script/basic/es6/const-tdz.js.EXPECTED
@@ -0,0 +1,9 @@
+test 1
+ReferenceError: "a" is not defined
+1
+test 2
+ReferenceError: "a" is not defined
+2
+test 3
+ReferenceError: "a" is not defined
+3
diff --git a/test/script/basic/es6/const.js b/test/script/basic/es6/const.js
new file mode 100644
index 00000000..100ce25a
--- /dev/null
+++ b/test/script/basic/es6/const.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+const a = 2;
+const c = 2;
+print(a, c);
+
+function f(x) {
+ const a = 5;
+ const c = 10;
+ print(a, c);
+ if (x) {
+ const a = 42;
+ const c = 43;
+ print(a, c);
+ }
+ print(a, c);
+
+ function inner() {
+ (function() {
+ print(a, c);
+ })();
+ }
+ inner();
+}
+
+f(true);
+f(false);
+
+(function() {
+ (function() {
+ print(a, c);
+ })();
+})();
+
+function outer() {
+ print(a, c);
+}
+outer();
diff --git a/test/script/basic/es6/const.js.EXPECTED b/test/script/basic/es6/const.js.EXPECTED
new file mode 100644
index 00000000..b7e50ef2
--- /dev/null
+++ b/test/script/basic/es6/const.js.EXPECTED
@@ -0,0 +1,10 @@
+2 2
+5 10
+42 43
+5 10
+5 10
+5 10
+5 10
+5 10
+2 2
+2 2
diff --git a/test/script/basic/es6/for-let-object-fields.js b/test/script/basic/es6/for-let-object-fields.js
new file mode 100644
index 00000000..fe44eda5
--- /dev/null
+++ b/test/script/basic/es6/for-let-object-fields.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8067219: NPE in ScriptObject.clone() when running with object fields
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.fields.objects=true
+ * @option --language=es6
+ */
+
+"use strict";
+
+for (let i = 0; i < 10; i++) {
+ print(i);
+}
+
+try {
+ print(i);
+} catch (e) {
+ print(e);
+}
+
+let a = [];
+
+for (let i = 0; i < 10; i++) {
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+a = [];
+
+for (let i = 0; i < 10; i++) {
+ if (i == 5) {
+ i = "foo";
+ }
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+try {
+ print(i);
+} catch (e) {
+ print(e);
+}
+
+a = [];
+
+for (let i = 0; i < 20; i++) {
+ if (i % 2 == 1) {
+ i += 2;
+ continue;
+ }
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
diff --git a/test/script/basic/es6/for-let-object-fields.js.EXPECTED b/test/script/basic/es6/for-let-object-fields.js.EXPECTED
new file mode 100644
index 00000000..21787adb
--- /dev/null
+++ b/test/script/basic/es6/for-let-object-fields.js.EXPECTED
@@ -0,0 +1,33 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+ReferenceError: "i" is not defined
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+0
+1
+2
+3
+4
+foo
+ReferenceError: "i" is not defined
+0
+4
+8
+12
+16
diff --git a/test/script/basic/es6/for-let.js b/test/script/basic/es6/for-let.js
new file mode 100644
index 00000000..2ad38e57
--- /dev/null
+++ b/test/script/basic/es6/for-let.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+for (let i = 0; i < 10; i++) {
+ print(i);
+}
+
+try {
+ print(i);
+} catch (e) {
+ print(e);
+}
+
+let a = [];
+
+for (let i = 0; i < 10; i++) {
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+a = [];
+
+for (let i = 0; i < 10; i++) {
+ if (i == 5) {
+ i = "foo";
+ }
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+try {
+ print(i);
+} catch (e) {
+ print(e);
+}
+
+a = [];
+
+for (let i = 0; i < 20; i++) {
+ if (i % 2 == 1) {
+ i += 2;
+ continue;
+ }
+ a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
diff --git a/test/script/basic/es6/for-let.js.EXPECTED b/test/script/basic/es6/for-let.js.EXPECTED
new file mode 100644
index 00000000..21787adb
--- /dev/null
+++ b/test/script/basic/es6/for-let.js.EXPECTED
@@ -0,0 +1,33 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+ReferenceError: "i" is not defined
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+0
+1
+2
+3
+4
+foo
+ReferenceError: "i" is not defined
+0
+4
+8
+12
+16
diff --git a/test/script/basic/es6/let-const-statement-context.js b/test/script/basic/es6/let-const-statement-context.js
new file mode 100644
index 00000000..3e662378
--- /dev/null
+++ b/test/script/basic/es6/let-const-statement-context.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057980: let & const: remaining issues with lexical scoping
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function tryEval(s) {
+ try {
+ eval(s);
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+ }
+}
+
+tryEval('if (true) let x = 1;');
+tryEval('if (true) const x = 1;');
+tryEval('while (true) let x = 1;');
+tryEval('while (true) const x = 1;');
+tryEval('for (;;) let x = 1;');
+tryEval('for (;;) const x = 1;');
+tryEval('do let x = 1; while (true);');
+tryEval('do const x = 1; while (true);');
+tryEval('with (y) const x = 1;');
+tryEval('with (y) let x = 1;');
diff --git a/test/script/basic/es6/let-const-statement-context.js.EXPECTED b/test/script/basic/es6/let-const-statement-context.js.EXPECTED
new file mode 100644
index 00000000..1b73e4c7
--- /dev/null
+++ b/test/script/basic/es6/let-const-statement-context.js.EXPECTED
@@ -0,0 +1,30 @@
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found let declaration
+if (true) let x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found const declaration
+if (true) const x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found let declaration
+while (true) let x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found const declaration
+while (true) const x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
+for (;;) let x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
+for (;;) const x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found let declaration
+do let x = 1; while (true);
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found const declaration
+do const x = 1; while (true);
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
+with (y) const x = 1;
+ ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
+with (y) let x = 1;
+ ^
diff --git a/test/script/basic/es6/let-const-switch.js b/test/script/basic/es6/let-const-switch.js
new file mode 100644
index 00000000..8a538b80
--- /dev/null
+++ b/test/script/basic/es6/let-const-switch.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057980: let & const: remaining issues with lexical scoping
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function tryEval(s) {
+ try {
+ eval(s);
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+ }
+}
+
+tryEval('var x = 0; switch (x) { case 0: { let x = 1; print(x); } case 1: { let x = 2; print(x); }} print(x);');
+tryEval('var x = 0; switch (x) { case 0: { const x = 1; print(x); } case 1: { const x = 2; print(x); }} print(x);');
+
+// TODO: the following should not throw
+tryEval('switch (x) { case 0: let x = 1; }');
+tryEval('switch (x) { case 0: const x = 1; }');
diff --git a/test/script/basic/es6/let-const-switch.js.EXPECTED b/test/script/basic/es6/let-const-switch.js.EXPECTED
new file mode 100644
index 00000000..90309bfe
--- /dev/null
+++ b/test/script/basic/es6/let-const-switch.js.EXPECTED
@@ -0,0 +1,12 @@
+1
+2
+0
+1
+2
+0
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:25 Unsupported let declaration in unprotected switch statement
+switch (x) { case 0: let x = 1; }
+ ^
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:27 Unsupported const declaration in unprotected switch statement
+switch (x) { case 0: const x = 1; }
+ ^
diff --git a/test/script/basic/es6/let-eval.js b/test/script/basic/es6/let-eval.js
new file mode 100644
index 00000000..b08fa98a
--- /dev/null
+++ b/test/script/basic/es6/let-eval.js
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+function f() {
+ var a;
+ let b;
+ const c = 0;
+
+ print(a, b, c);
+
+ try {
+ eval("x = 1; print('x: ' + x);");
+ print("assignment to x succeeded");
+ } catch (e) {
+ print(e);
+ }
+ try {
+ eval("'use strict'; let z = 1; print('z: ' + z);");
+ print("assignment to z succeeded");
+ eval("print('z: ' + z);");
+ } catch (e) {
+ print(e);
+ }
+
+ try {
+ eval("a = 1; print(a);");
+ print("assignment to a succeeded");
+ } catch (e) {
+ print(e);
+ }
+ print("a: " + a);
+
+ try {
+ eval("b = 1; print('b: ' + b);");
+ print("assignment to b succeeded");
+ } catch (e) {
+ print(e);
+ }
+ print("b: " + b);
+
+ try {
+ eval("c = 1; print('c: ' + c);");
+ print("assignment to c succeeded");
+ } catch (e) {
+ print(e);
+ }
+ print("c: " + c);
+
+ eval("a = 2; let b = 3;");
+
+ try {
+ print(a, b, c);
+ } catch (e) {
+ print(e);
+ }
+
+ let x;
+
+ try {
+ print(a, b, c, x);
+ } catch (e) {
+ print(e);
+ }
+
+}
+
+f();
+
+print(typeof a, typeof b, typeof c, typeof x, typeof z);
diff --git a/test/script/basic/es6/let-eval.js.EXPECTED b/test/script/basic/es6/let-eval.js.EXPECTED
new file mode 100644
index 00000000..96f9a6d0
--- /dev/null
+++ b/test/script/basic/es6/let-eval.js.EXPECTED
@@ -0,0 +1,16 @@
+undefined undefined 0
+ReferenceError: "x" is not defined
+z: 1
+assignment to z succeeded
+ReferenceError: "z" is not defined
+1
+assignment to a succeeded
+a: 1
+b: 1
+assignment to b succeeded
+b: 1
+TypeError: "c" is not a writable property of [object Object]
+c: 0
+2 1 0
+2 1 0 undefined
+undefined undefined undefined undefined undefined
diff --git a/test/script/basic/es6/let-load-lib.js b/test/script/basic/es6/let-load-lib.js
new file mode 100644
index 00000000..2cfa4112
--- /dev/null
+++ b/test/script/basic/es6/let-load-lib.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @subtest
+ */
+
+"use strict";
+
+// var should be visible in other script, let and const not
+var a = 1;
+let b = 2;
+const c = 3;
+
+// top level function should be visible
+function top() {
+ print("top level function");
+}
+
+// block level function not visible outside script
+{
+ function block() {
+ print("block function");
+ }
+
+ top();
+ block();
+}
diff --git a/test/script/basic/es6/let-load.js b/test/script/basic/es6/let-load.js
new file mode 100644
index 00000000..ff8f4e1c
--- /dev/null
+++ b/test/script/basic/es6/let-load.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+"use strict";
+
+load(__DIR__ + "let-load-lib.js");
+
+{
+ let a = 20;
+ const c = 30;
+ print("print local defs: " + a, c);
+}
+
+print("imported var: " + a);
+print("imported let: " + b);
+print("imported const: " + c);
+
+top();
+
+try {
+ block();
+} catch (e) {
+ print(e);
+}
+
+try {
+ c = "foo";
+} catch (e) {
+ print(e);
+}
+
+
diff --git a/test/script/basic/es6/let-load.js.EXPECTED b/test/script/basic/es6/let-load.js.EXPECTED
new file mode 100644
index 00000000..a0b2e094
--- /dev/null
+++ b/test/script/basic/es6/let-load.js.EXPECTED
@@ -0,0 +1,9 @@
+top level function
+block function
+print local defs: 20 30
+imported var: 1
+imported let: 2
+imported const: 3
+top level function
+ReferenceError: "block" is not defined
+TypeError: Assignment to constant "c"
diff --git a/test/script/basic/es6/let-nodeclare.js b/test/script/basic/es6/let-nodeclare.js
new file mode 100644
index 00000000..3142d22f
--- /dev/null
+++ b/test/script/basic/es6/let-nodeclare.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+try {
+ if (true) {
+ let x = 2;
+ print(x);
+ }
+ print(x);
+} catch (e) {
+ print(e);
+}
+
+
+try {
+ if (true) {
+ const x = 2;
+ print(x);
+ }
+ print(x);
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/es6/let-nodeclare.js.EXPECTED b/test/script/basic/es6/let-nodeclare.js.EXPECTED
new file mode 100644
index 00000000..4c4052c2
--- /dev/null
+++ b/test/script/basic/es6/let-nodeclare.js.EXPECTED
@@ -0,0 +1,4 @@
+2
+ReferenceError: "x" is not defined
+2
+ReferenceError: "x" is not defined
diff --git a/test/script/basic/es6/let-redeclare-extra.js b/test/script/basic/es6/let-redeclare-extra.js
new file mode 100644
index 00000000..ddb205e4
--- /dev/null
+++ b/test/script/basic/es6/let-redeclare-extra.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"))
+ }
+}
+
+tryIt(<<CODE
+ "use strict";
+ let x = 2;
+ const x = function (a,b,c) {};
+CODE)
+
+tryIt(<<CODE
+ "use strict";
+ let x = {};
+ var x = 2;
+CODE)
+
+tryIt(<<CODE
+ "use strict";
+ var x = 2;
+ let x = undefined;
+CODE)
+
+tryIt(<<CODE
+ "use strict";
+ const x = function (){};
+ let x = {};
+CODE)
+
+
+tryIt(<<CODE
+ "use strict";
+ let a = 2;
+ function a () {};
+CODE) \ No newline at end of file
diff --git a/test/script/basic/es6/let-redeclare-extra.js.EXPECTED b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED
new file mode 100644
index 00000000..e0e1afec
--- /dev/null
+++ b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED
@@ -0,0 +1,15 @@
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
+ let x = 2;
+ ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
+ var x = 2;
+ ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
+ let x = undefined;
+ ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
+ const x = function (){};
+ ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "a" has already been declared
+ let a = 2;
+ ^
diff --git a/test/script/basic/es6/let-redeclare.js b/test/script/basic/es6/let-redeclare.js
new file mode 100644
index 00000000..adc05196
--- /dev/null
+++ b/test/script/basic/es6/let-redeclare.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+ eval('"use strict";\n' +
+ 'let x = 2;\n' +
+ 'let x = 2;\n');
+} catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+}
diff --git a/test/script/basic/es6/let-redeclare.js.EXPECTED b/test/script/basic/es6/let-redeclare.js.EXPECTED
new file mode 100644
index 00000000..299e35ef
--- /dev/null
+++ b/test/script/basic/es6/let-redeclare.js.EXPECTED
@@ -0,0 +1,3 @@
+SyntaxError: test/script/basic/es6/let-redeclare.js#33:4<eval>:2:4 Variable "x" has already been declared
+let x = 2;
+ ^
diff --git a/test/script/basic/es6/let-self.js b/test/script/basic/es6/let-self.js
new file mode 100644
index 00000000..707739bf
--- /dev/null
+++ b/test/script/basic/es6/let-self.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+let a, b = a;
+
+print(a, b);
+
+try {
+ eval('"use strict";\n' +
+ 'let a = a;\n');
+} catch (e) {
+ print(e);
+}
diff --git a/test/script/basic/es6/let-self.js.EXPECTED b/test/script/basic/es6/let-self.js.EXPECTED
new file mode 100644
index 00000000..32b789a1
--- /dev/null
+++ b/test/script/basic/es6/let-self.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined undefined
+ReferenceError: "a" is not defined
diff --git a/test/script/basic/es6/let-tdz.js b/test/script/basic/es6/let-tdz.js
new file mode 100644
index 00000000..da61a61a
--- /dev/null
+++ b/test/script/basic/es6/let-tdz.js
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+{
+ print("test 1");
+
+ function f() {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ f();
+ let a = 1;
+ f();
+}
+
+{
+ print("test 2");
+
+ function f() {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ f();
+ let a = 2;
+ f();
+}
+
+{
+ print("test 3");
+
+ {
+ try {
+ print(a);
+ } catch (a) {
+ print(a);
+ }
+ }
+
+ let a = 3;
+
+ {
+ print(a);
+ }
+}
+
+{
+ print("test 4");
+ let a;
+
+ {
+ print(a);
+ }
+
+ a = 4;
+
+ {
+ print(a);
+ }
+}
+
diff --git a/test/script/basic/es6/let-tdz.js.EXPECTED b/test/script/basic/es6/let-tdz.js.EXPECTED
new file mode 100644
index 00000000..48a81251
--- /dev/null
+++ b/test/script/basic/es6/let-tdz.js.EXPECTED
@@ -0,0 +1,12 @@
+test 1
+ReferenceError: "a" is not defined
+1
+test 2
+ReferenceError: "a" is not defined
+2
+test 3
+ReferenceError: "a" is not defined
+3
+test 4
+undefined
+4
diff --git a/test/script/basic/es6/let.js b/test/script/basic/es6/let.js
new file mode 100644
index 00000000..1051ae54
--- /dev/null
+++ b/test/script/basic/es6/let.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051889: Implement block scoping in symbol assignment and scope computation
+ *
+ * @test
+ * @run
+ * @option --language=es6 */
+
+"use strict";
+
+let a = 2;
+let c = 2;
+print(a, c);
+
+function f(x) {
+ let a = 5;
+ const c = 10;
+ print(a, c);
+ if (x) {
+ let a = 42;
+ const c = 43;
+ print(a, c);
+ }
+ print(a, c);
+
+ function inner() {
+ (function() {
+ print(a, c);
+ })();
+ }
+ inner();
+}
+
+f(true);
+f(false);
+
+(function() {
+ (function() {
+ print(a, c);
+ })();
+})();
+
+function outer() {
+ print(a, c);
+}
+outer();
+
diff --git a/test/script/basic/es6/let.js.EXPECTED b/test/script/basic/es6/let.js.EXPECTED
new file mode 100644
index 00000000..b7e50ef2
--- /dev/null
+++ b/test/script/basic/es6/let.js.EXPECTED
@@ -0,0 +1,10 @@
+2 2
+5 10
+42 43
+5 10
+5 10
+5 10
+5 10
+5 10
+2 2
+2 2
diff --git a/test/script/basic/es6/let_const_closure.js b/test/script/basic/es6/let_const_closure.js
new file mode 100644
index 00000000..43da4713
--- /dev/null
+++ b/test/script/basic/es6/let_const_closure.js
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt(code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(e)
+ }
+}
+
+
+tryIt(<<CODE
+ function a () {
+ this.val = 41
+ let self = this
+ this.b = function () {
+ return self.val;
+ }
+ }
+ c = new a()
+ print(c.b.call(null))
+CODE)
+
+
+tryIt(<<CODE
+ function a () {
+ this.val = 42
+ let self = this
+ this.b = function () {
+ return this.val;
+ }.bind(self)
+ }
+ c = new a()
+ print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+ function a () {
+ this.val = 43
+ const self = this
+ this.b = function () {
+ return self.val;
+ }
+ }
+ c = new a()
+ print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+ function a () {
+ this.val = 44
+ const self = this
+ this.b = function () {
+ return this.val;
+ }.bind(self)
+ }
+ c = new a()
+ print(c.b.call(null))
+CODE)
+
+tryIt(<<CODE
+ let a = {name : 'test'}
+ let f = function () {
+ print(this.name)
+ }
+ let nf = f.bind(a)
+ nf()
+ if (true) {
+ let a = null
+ nf()
+ }
+ nf()
+CODE)
+
+
+tryIt(<<CODE
+ let arr = []
+ for (let i = 0; i < 3; i++) {
+ arr[i] = function(){return i;}
+ }
+ for (let i in arr) {
+ print(arr[i]())
+ }
+ arr = []
+ for (var i = 0; i < 3; i++) {
+ (function(i){
+ arr[i] = function(){return i;}
+ })(i)
+ }
+ for (let i in arr) {
+ print(arr[i]())
+ }
+CODE) \ No newline at end of file
diff --git a/test/script/basic/es6/let_const_closure.js.EXPECTED b/test/script/basic/es6/let_const_closure.js.EXPECTED
new file mode 100644
index 00000000..f49ca4b9
--- /dev/null
+++ b/test/script/basic/es6/let_const_closure.js.EXPECTED
@@ -0,0 +1,13 @@
+41
+42
+43
+44
+test
+test
+test
+0
+1
+2
+0
+1
+2
diff --git a/test/script/basic/es6/let_const_reuse.js b/test/script/basic/es6/let_const_reuse.js
new file mode 100644
index 00000000..bc9e8f84
--- /dev/null
+++ b/test/script/basic/es6/let_const_reuse.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"))
+ }
+}
+
+tryIt(<<CODE
+ let a = 23
+ if (true) {
+ a--
+ let a = 43;
+ }
+CODE)
+
+tryIt(<<CODE
+ const a = 23
+ if (true) {
+ a--
+ const a = 43;
+ }
+CODE)
+
+tryIt(<<CODE
+ let a = 23
+ if (true) {
+ a--
+ const a = 43;
+ }
+CODE)
+
+tryIt(<<CODE
+ const a = 23
+ if (true) {
+ a--
+ let a = 43;
+ }
+CODE)
diff --git a/test/script/basic/es6/let_const_reuse.js.EXPECTED b/test/script/basic/es6/let_const_reuse.js.EXPECTED
new file mode 100644
index 00000000..fa875c7a
--- /dev/null
+++ b/test/script/basic/es6/let_const_reuse.js.EXPECTED
@@ -0,0 +1,8 @@
+ReferenceError: "a" is not defined
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+ a--
+ ^
+SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
+ a--
+ ^
+ReferenceError: "a" is not defined
diff --git a/test/script/basic/es6/let_different_types.js b/test/script/basic/es6/let_different_types.js
new file mode 100644
index 00000000..39ff246d
--- /dev/null
+++ b/test/script/basic/es6/let_different_types.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(e)
+ }
+}
+
+tryIt(<<CODE
+ let a = function () { var a = "Hello World!"; return a; }
+ print(typeof a)
+ {
+ let a = 34;
+ print(typeof a)
+ if (true) {
+ let c = 54.7
+ var d = c
+ print(typeof c)
+ print(typeof d)
+ }
+ }
+ print(typeof a)
+ print(typeof a())
+ print(typeof c)
+ print(typeof d)
+ print(d)
+CODE)
+
+tryIt(<<CODE
+ let a = {}
+ if (true) {
+ function a () {
+ print (typeof a)
+ return 'Hello World!'
+ }
+ print(typeof a)
+ print(a())
+ }
+ print(typeof a)
+CODE)
+
diff --git a/test/script/basic/es6/let_different_types.js.EXPECTED b/test/script/basic/es6/let_different_types.js.EXPECTED
new file mode 100644
index 00000000..47eceaeb
--- /dev/null
+++ b/test/script/basic/es6/let_different_types.js.EXPECTED
@@ -0,0 +1,13 @@
+function
+number
+number
+number
+function
+string
+undefined
+number
+54.7
+function
+function
+Hello World!
+object
diff --git a/test/script/basic/es6/let_loops.js b/test/script/basic/es6/let_loops.js
new file mode 100644
index 00000000..54dba1f1
--- /dev/null
+++ b/test/script/basic/es6/let_loops.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057678: Tests for let&const keywords in Nashorn
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -scripting
+ */
+
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(e)
+ }
+}
+
+tryIt(<<CODE
+ let a = 2;
+ do {
+ a--;
+ let b = a;
+ } while (a > 0);
+ print(a)
+ print(b)
+CODE)
+
+tryIt(<<CODE
+ let a = 2
+ while(a > 0) {
+ a--
+ let b = a
+ }
+ print(a)
+ print(b)
+CODE)
+
+tryIt(<<CODE
+ let a = 2
+ while(a > 0) {
+ a--
+ const b = a
+ }
+ print(a)
+ print(b)
+CODE)
+
+tryIt(<<CODE
+ let a = 2;
+ do {
+ a--;
+ const b = a;
+ } while (a > 0);
+ print(a)
+ print(b)
+CODE)
diff --git a/test/script/basic/es6/let_loops.js.EXPECTED b/test/script/basic/es6/let_loops.js.EXPECTED
new file mode 100644
index 00000000..8a0c63e5
--- /dev/null
+++ b/test/script/basic/es6/let_loops.js.EXPECTED
@@ -0,0 +1,8 @@
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
+0
+ReferenceError: "b" is not defined
diff --git a/test/script/basic/es6/lexical-toplevel-def.js b/test/script/basic/es6/lexical-toplevel-def.js
new file mode 100644
index 00000000..c9a44f70
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-def.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+var VAR = "VAR";
+let LET = "LET";
+const CONST = "CONST";
+function FUNC() {}
+this.GLOBAL = "GLOBAL";
diff --git a/test/script/basic/es6/lexical-toplevel-print.js b/test/script/basic/es6/lexical-toplevel-print.js
new file mode 100644
index 00000000..eef030ac
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-print.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+print(VAR);
+print(LET);
+print(CONST);
+print(FUNC);
+print(GLOBAL);
+print(this.VAR);
+print(this.LET); // undefined
+print(this.CONST); // undefined
+print(this.FUNC);
+print(this.GLOBAL);
+print("VAR" in this);
+print("LET" in this); // false
+print("CONST" in this); // false
+print("FUNC" in this);
+print("GLOBAL" in this);
+
+try {
+ LET = LET + "LET";
+ CONST = CONST + "CONST";
+} catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+}
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js b/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js
new file mode 100644
index 00000000..bfe7af35
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+function LET() {}
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js
new file mode 100644
index 00000000..64360142
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let Object = "LEXICAL BUILTIN";
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js
new file mode 100644
index 00000000..44c83964
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let FUNC = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js
new file mode 100644
index 00000000..a742fad3
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let GLOBAL = "LEXICAL GLOBAL";
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js
new file mode 100644
index 00000000..630741f0
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let VAR = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js b/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js
new file mode 100644
index 00000000..cb4b3822
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+var LET = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare.js b/test/script/basic/es6/lexical-toplevel-redeclare.js
new file mode 100644
index 00000000..6a76622f
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @test
+ * @run
+ * @option -scripting
+ * @option --language=es6
+ */
+
+load(__DIR__ + "lexical-toplevel-def.js");
+
+var global = this;
+
+function tryIt (code) {
+ try {
+ eval(code)
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"))
+ }
+}
+
+function loadScript(script) {
+ print(script);
+ try {
+ load(__DIR__ + script);
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+ }
+ print(VAR);
+ print(LET);
+ print(CONST);
+ print(FUNC);
+ print(GLOBAL);
+ print(global.VAR);
+ print(global.LET);
+ print(global.CONST);
+ print(global.FUNC);
+ print(global.GLOBAL);
+ try {
+ print(SHOULD_NOT_EXIST);
+ } catch (e) {
+ print(String(e).replace(/\\/g, "/"));
+ }
+ print(global.SHOULD_NOT_EXIST);
+ print(Object);
+ print(global.Object);
+ print();
+}
+
+loadScript("lexical-toplevel-redeclare-var-on-let.js");
+loadScript("lexical-toplevel-redeclare-func-on-let.js");
+loadScript("lexical-toplevel-redeclare-let-on-var.js");
+loadScript("lexical-toplevel-redeclare-let-on-func.js");
+loadScript("lexical-toplevel-redeclare-let-on-builtin.js");
+loadScript("lexical-toplevel-redeclare-let-on-global.js");
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED b/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED
new file mode 100644
index 00000000..d1471c80
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED
@@ -0,0 +1,100 @@
+lexical-toplevel-redeclare-var-on-let.js
+SyntaxError: Variable "LET" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-func-on-let.js
+SyntaxError: Variable "LET" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-var.js
+SyntaxError: Variable "VAR" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-func.js
+SyntaxError: Variable "FUNC" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-builtin.js
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+LEXICAL BUILTIN
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-global.js
+VAR
+LET
+CONST
+function FUNC() {}
+LEXICAL GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+LEXICAL BUILTIN
+function Object() { [native code] }
+
diff --git a/test/script/basic/es6/lexical-toplevel.js b/test/script/basic/es6/lexical-toplevel.js
new file mode 100644
index 00000000..fc272a8a
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+load(__DIR__ + "lexical-toplevel-def.js");
+
+load(__DIR__ + "lexical-toplevel-print.js");
+load(__DIR__ + "lexical-toplevel-print.js");
diff --git a/test/script/basic/es6/lexical-toplevel.js.EXPECTED b/test/script/basic/es6/lexical-toplevel.js.EXPECTED
new file mode 100644
index 00000000..7580af4f
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel.js.EXPECTED
@@ -0,0 +1,32 @@
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+true
+false
+false
+true
+true
+TypeError: Assignment to constant "CONST"
+VAR
+LETLET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+true
+false
+false
+true
+true
+TypeError: Assignment to constant "CONST"
diff --git a/test/script/basic/eval.js b/test/script/basic/eval.js
index 3d66c028..59402d4f 100644
--- a/test/script/basic/eval.js
+++ b/test/script/basic/eval.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* eval test.
*
* @test
- * @run
+ * @run
*/
print("eval.length " + eval.length);
@@ -33,7 +33,7 @@ print("eval.length " + eval.length);
function test1() {
var x = 200;
y = x + 2000;
-
+
print(x);
print(y);
}
@@ -41,7 +41,7 @@ function test1() {
function test2() {
eval("var x = 300;");
eval("y = x + 3000;");
-
+
print(x);
print(y);
}
diff --git a/test/script/basic/evalreturn.js b/test/script/basic/evalreturn.js
index 3f523cc7..75d02a88 100644
--- a/test/script/basic/evalreturn.js
+++ b/test/script/basic/evalreturn.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* eval return values test.
*
* @test
- * @run
+ * @run
*/
var x = 0;
@@ -65,7 +65,7 @@ f();
var g = eval("function cake() { print('moist and delicious!'); } function cookie() { print('sweet and crunchy!'); }");
print(g);
g();
-
+
diff --git a/test/script/basic/exprclosure.js b/test/script/basic/exprclosure.js
index ad1c3965..45bc9082 100644
--- a/test/script/basic/exprclosure.js
+++ b/test/script/basic/exprclosure.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/exprclosure.js.EXPECTED b/test/script/basic/exprclosure.js.EXPECTED
index ae803384..9afb92a4 100644
--- a/test/script/basic/exprclosure.js.EXPECTED
+++ b/test/script/basic/exprclosure.js.EXPECTED
@@ -1,4 +1,4 @@
-function(x) x*x;
+function(x) x*x
625
-function fun(x) x * (x + 1) / 2;
+function fun(x) x * (x + 1) / 2
55
diff --git a/test/script/basic/extensibility.js b/test/script/basic/extensibility.js
index 09044667..2cf76528 100644
--- a/test/script/basic/extensibility.js
+++ b/test/script/basic/extensibility.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/fastpushpop.js b/test/script/basic/fastpushpop.js
new file mode 100644
index 00000000..fffd3f23
--- /dev/null
+++ b/test/script/basic/fastpushpop.js
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * fastpushpop.js: make sure guards work for fast push implementation
+ * and normal one
+ *
+ * @test
+ * @run
+ */
+
+var a = [1,2,3];
+a.push(4);
+a.push(5);
+a.push(6);
+print(a);
+
+var a2 = Object.defineProperty(a,"length", { writable: false });
+try {
+ a2.push(7);
+} catch (e) {
+ print("first: " + (e instanceof TypeError));
+}
+
+print(a2);
+
+var b = [1,2,3,,,,4711.17,"dingo!"];
+b.push(4);
+b.push(5);
+b.push(6);
+print(b);
+
+var b2 = Object.defineProperty(b,"length", { writable: false });
+try {
+ b2.push(7);
+} catch (e) {
+ print("second: " + (e instanceof TypeError));
+}
+
+print(b2);
+
diff --git a/test/script/basic/fastpushpop.js.EXPECTED b/test/script/basic/fastpushpop.js.EXPECTED
new file mode 100644
index 00000000..870770d3
--- /dev/null
+++ b/test/script/basic/fastpushpop.js.EXPECTED
@@ -0,0 +1,6 @@
+1,2,3,4,5,6
+first: true
+1,2,3,4,5,6
+1,2,3,,,,4711.17,dingo!,4,5,6
+second: true
+1,2,3,,,,4711.17,dingo!,4,5,6
diff --git a/test/script/basic/fileline.js b/test/script/basic/fileline.js
index ccf879b2..90b3d58c 100644
--- a/test/script/basic/fileline.js
+++ b/test/script/basic/fileline.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/finally-catchalls.js b/test/script/basic/finally-catchalls.js
index dac9cee9..f6f38961 100644
--- a/test/script/basic/finally-catchalls.js
+++ b/test/script/basic/finally-catchalls.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,75 +30,75 @@
function test1() {
try {
- print("try");
- throw "ex";
+ print("try");
+ throw "ex";
} finally {
- print("finally");
+ print("finally");
}
}
-function test2() {
+function test2() {
try {
- print("try");
+ print("try");
} finally {
- print("finally");
+ print("finally");
}
}
-function test3() {
+function test3() {
try {
- print("try");
- return;
+ print("try");
+ return;
} finally {
- print("finally");
+ print("finally");
}
}
-function test4() {
+function test4() {
var i = 0;
while (i<10) {
- try {
- print("try "+i);
- i++;
- continue;
- } finally {
- print("finally "+i);
- }
+ try {
+ print("try "+i);
+ i++;
+ continue;
+ } finally {
+ print("finally "+i);
+ }
}
print(i);
}
-function test5() {
+function test5() {
var i = 0;
while (i<10) {
- try {
- print("try "+i);
- i++;
- break;
- } finally {
- print("finally "+i);
- }
+ try {
+ print("try "+i);
+ i++;
+ break;
+ } finally {
+ print("finally "+i);
+ }
}
print(i);
}
-function test6() {
+function test6() {
var i = 0;
while (i<10) {
- try {
- print("try "+i);
- if (i == 5)
- break;
- i++;
- } finally {
- print("finally "+i);
- }
+ try {
+ print("try "+i);
+ if (i == 5)
+ break;
+ i++;
+ } finally {
+ print("finally "+i);
+ }
}
print(i);
}
print("\ntest 1\n");
-try {
+try {
test1();
} catch (e) {
print("got e");
diff --git a/test/script/basic/finallyreturn.js b/test/script/basic/finallyreturn.js
index 79c9f715..6593f176 100644
--- a/test/script/basic/finallyreturn.js
+++ b/test/script/basic/finallyreturn.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/forin.js b/test/script/basic/forin.js
index 2a60a660..4b1b85a5 100644
--- a/test/script/basic/forin.js
+++ b/test/script/basic/forin.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/forin2.js b/test/script/basic/forin2.js
index be47bec2..04010625 100644
--- a/test/script/basic/forin2.js
+++ b/test/script/basic/forin2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -37,7 +37,7 @@ try {
print("error 1");
} catch(e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
@@ -46,30 +46,30 @@ try {
print("error 2");
} catch(e) {
if((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
-try {
- for (var y in null) {
- y = 2;
+try {
+ for (var y in null) {
+ y = 2;
}
print("this is ok 1");
} catch(e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
// CHECK#4
try {
- for (var z in 'bbb'.match(/aaa/)) {
- z = 2;
+ for (var z in 'bbb'.match(/aaa/)) {
+ z = 2;
}
print("this is ok 2");
} catch(e) {
if((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
@@ -79,7 +79,7 @@ try {
print("error 5");
} catch(e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
@@ -88,29 +88,29 @@ try {
print("error 6");
} catch (e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
// CHECK#3
try {
- for (var y in undefined) {
- y = 2;
+ for (var y in undefined) {
+ y = 2;
}
print("this is ok 3");
-} catch (e) {
+} catch (e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
try {
- for (var z in this.foo) {
- z = 2;
+ for (var z in this.foo) {
+ z = 2;
}
print("this is ok 4");
} catch (e) {
if ((e instanceof TypeError) !== true) {
- print(e);
+ print(e);
}
}
diff --git a/test/script/basic/funcarray.js b/test/script/basic/funcarray.js
index 7ffd5f58..a55443a5 100644
--- a/test/script/basic/funcarray.js
+++ b/test/script/basic/funcarray.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,9 +25,9 @@
* Function array test.
*
* @test
- * @run
+ * @run
*/
-
+
var funcs = [
function() { print("first"); },
@@ -35,7 +35,7 @@ var funcs = [
function() { print("third"); },
function() { print("fourth"); }
];
-
+
funcs[0]();
funcs[1]();
funcs[2]();
diff --git a/test/script/basic/funcbind.js b/test/script/basic/funcbind.js
index 2b97b0ea..bb139530 100644
--- a/test/script/basic/funcbind.js
+++ b/test/script/basic/funcbind.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,10 +34,10 @@ function foo() {
print("global foo");
}
-function func(x, y) {
+function func(x, y) {
print(this == global);
- print(x);
- print(y);
+ print(x);
+ print(y);
this.foo();
}
diff --git a/test/script/basic/funcbind2.js b/test/script/basic/funcbind2.js
index 697ee529..16016b56 100644
--- a/test/script/basic/funcbind2.js
+++ b/test/script/basic/funcbind2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/funcbind3.js b/test/script/basic/funcbind3.js
index 25f448d2..10cf9cae 100644
--- a/test/script/basic/funcbind3.js
+++ b/test/script/basic/funcbind3.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/funcconstructor.js b/test/script/basic/funcconstructor.js
index 038031cd..4fc096a6 100644
--- a/test/script/basic/funcconstructor.js
+++ b/test/script/basic/funcconstructor.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/getclassname.js b/test/script/basic/getclassname.js
index 3e29bc64..dd94b03c 100644
--- a/test/script/basic/getclassname.js
+++ b/test/script/basic/getclassname.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/getter_callsite.js b/test/script/basic/getter_callsite.js
index 1e0800f0..0d72344a 100644
--- a/test/script/basic/getter_callsite.js
+++ b/test/script/basic/getter_callsite.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Check that getter property is properly invoked by a callsite
- *
+ *
* @test
* @run
*/
@@ -32,7 +32,7 @@ function newObj(a) {
return { get foo() { return a }};
}
-function printFoo(obj) {
+function printFoo(obj) {
print("obj.foo is " + obj.foo);
}
diff --git a/test/script/basic/gettercalls.js b/test/script/basic/gettercalls.js
index 200f1cea..fe69e670 100644
--- a/test/script/basic/gettercalls.js
+++ b/test/script/basic/gettercalls.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/getterfunc.js b/test/script/basic/getterfunc.js
index 2c2cc4bf..d3ce6f31 100644
--- a/test/script/basic/getterfunc.js
+++ b/test/script/basic/getterfunc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/gettersetter.js b/test/script/basic/gettersetter.js
index 68106bc1..ff5e75aa 100644
--- a/test/script/basic/gettersetter.js
+++ b/test/script/basic/gettersetter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Getter/Setter test.
*
* @test
- * @run
+ * @run
*/
'use strict';
@@ -39,7 +39,7 @@ var a = {
this._x = x;
}
};
-
+
var b = {
_x : "default",
get x() {
@@ -47,7 +47,7 @@ var b = {
}
};
-
+
var c = {
_x : "default",
set x(x) {
diff --git a/test/script/basic/globalaccess.js b/test/script/basic/globalaccess.js
index 6e18cfab..282775a0 100644
--- a/test/script/basic/globalaccess.js
+++ b/test/script/basic/globalaccess.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/globals.js b/test/script/basic/globals.js
index 4e2b47f3..b3acfe28 100644
--- a/test/script/basic/globals.js
+++ b/test/script/basic/globals.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/globalscope.js b/test/script/basic/globalscope.js
index 7e87bdf8..db720456 100644
--- a/test/script/basic/globalscope.js
+++ b/test/script/basic/globalscope.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Global scope test.
*
* @test
- * @run
+ * @run
*/
var g = this;
diff --git a/test/script/basic/hello.js b/test/script/basic/hello.js
index 19fca9f7..278887b6 100644
--- a/test/script/basic/hello.js
+++ b/test/script/basic/hello.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Simple "hello world" test
*
* @test
- * @run
+ * @run
*/
print("hello world");
diff --git a/test/script/basic/herestr_operator.js b/test/script/basic/herestr_operator.js
index 0e5b8afd..25d898c8 100644
--- a/test/script/basic/herestr_operator.js
+++ b/test/script/basic/herestr_operator.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/hideLocationProperties.js b/test/script/basic/hideLocationProperties.js
new file mode 100644
index 00000000..62c1ec06
--- /dev/null
+++ b/test/script/basic/hideLocationProperties.js
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests the hiding of location properties by local variables etc.
+ *
+ * @test
+ * @run
+ */
+
+function x(__FILE__) {
+ print(__FILE__);
+}
+
+function y(__FILE__) {
+ print(__FILE__);
+ function y1() { __FILE__ }
+}
+
+function w(__FILE__) {
+ print(__FILE__);
+ return arguments;
+}
+
+function z(__FILE__) {
+ (function() { print(__FILE__) })()
+}
+
+print(__FILE__.replace(/\\/g, "/"))
+
+var o = { __FILE__: "woot" }
+with(o) { print(__FILE__) }
+
+x("foo")
+y("bar")
+w("boo")
+z("baz")
diff --git a/test/script/basic/hideLocationProperties.js.EXPECTED b/test/script/basic/hideLocationProperties.js.EXPECTED
new file mode 100644
index 00000000..3af2a389
--- /dev/null
+++ b/test/script/basic/hideLocationProperties.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/basic/hideLocationProperties.js
+woot
+foo
+bar
+boo
+baz
diff --git a/test/script/basic/illegaljavaname.js b/test/script/basic/illegaljavaname.js
index 20ccc5ac..44186cc1 100644
--- a/test/script/basic/illegaljavaname.js
+++ b/test/script/basic/illegaljavaname.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/importpackage.js b/test/script/basic/importpackage.js
index 9a2b3a3e..35b3a1fa 100644
--- a/test/script/basic/importpackage.js
+++ b/test/script/basic/importpackage.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/incheck.js b/test/script/basic/incheck.js
index 1571b624..db366e0b 100644
--- a/test/script/basic/incheck.js
+++ b/test/script/basic/incheck.js
@@ -1,30 +1,30 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * Check that the expression ("property" in obj) works for own property as
+ * Check that the expression ("property" in obj) works for own property as
* well as properties 'inherited' from proto chain.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/indexedcall.js b/test/script/basic/indexedcall.js
index b3f651b6..f0e5d65c 100644
--- a/test/script/basic/indexedcall.js
+++ b/test/script/basic/indexedcall.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/info.js b/test/script/basic/info.js
index 958572cc..3d27f8f2 100644
--- a/test/script/basic/info.js
+++ b/test/script/basic/info.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/inherited_nonwritable.js b/test/script/basic/inherited_nonwritable.js
index c7943320..db82658c 100644
--- a/test/script/basic/inherited_nonwritable.js
+++ b/test/script/basic/inherited_nonwritable.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/instanceof.js b/test/script/basic/instanceof.js
index 31878b55..05b91429 100644
--- a/test/script/basic/instanceof.js
+++ b/test/script/basic/instanceof.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/instanceof2.js b/test/script/basic/instanceof2.js
index a6c07c28..84c9b59a 100644
--- a/test/script/basic/instanceof2.js
+++ b/test/script/basic/instanceof2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Instanceof test.
*
* @test
- * @run
+ * @run
*/
var x = { a: 1, b: "string", c: [1, 2, 3], d: function() {} };
diff --git a/test/script/basic/interfaces.js b/test/script/basic/interfaces.js
index 1c42e9d2..bb668a68 100644
--- a/test/script/basic/interfaces.js
+++ b/test/script/basic/interfaces.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -28,7 +28,7 @@
* @run
*/
-// implement java.lang.Runnable interface
+// implement java.lang.Runnable interface
var runnable = new java.lang.Runnable({
run: function() {
print("Inside run function");
diff --git a/test/script/basic/iterator.js b/test/script/basic/iterator.js
index 0b70db4a..6f8f0f1b 100644
--- a/test/script/basic/iterator.js
+++ b/test/script/basic/iterator.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Verify that basic for..in works for objects, arrays.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/java.js b/test/script/basic/java.js
index b3aaea19..af4b3608 100644
--- a/test/script/basic/java.js
+++ b/test/script/basic/java.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/javaadapter.js b/test/script/basic/javaadapter.js
index 484a5d24..e8c9551d 100644
--- a/test/script/basic/javaadapter.js
+++ b/test/script/basic/javaadapter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/javaarray.js b/test/script/basic/javaarray.js
index 5a158889..727b926b 100644
--- a/test/script/basic/javaarray.js
+++ b/test/script/basic/javaarray.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/javaarrayconversion.js b/test/script/basic/javaarrayconversion.js
index 96ebe904..6168247a 100644
--- a/test/script/basic/javaarrayconversion.js
+++ b/test/script/basic/javaarrayconversion.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Tests for conversion of JavaScript arrays to Java arrays and the other
- * way round. Also generally useful as a JavaScript-to-Java type conversion
+ * way round. Also generally useful as a JavaScript-to-Java type conversion
* test.
*
* @test
@@ -49,9 +49,9 @@ function testNaN(inputValue, type) {
testF(inputValue, type, isNaN)
}
-// Those labeled "Correct?" are not clearly correct conversions. Those
-// labeled "TypeError maybe?" could actually throw a TypeError, or only
-// throw a TypeError when in strict mode.
+// Those labeled "Correct?" are not clearly correct conversions. Those
+// labeled "TypeError maybe?" could actually throw a TypeError, or only
+// throw a TypeError when in strict mode.
// The case of ("false", "boolean") => true is particularly amusing.
test(x, "int", 0) // Correct? TypeError maybe?
diff --git a/test/script/basic/javaclassoverrides.js b/test/script/basic/javaclassoverrides.js
index 2fa7a857..e9311922 100644
--- a/test/script/basic/javaclassoverrides.js
+++ b/test/script/basic/javaclassoverrides.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/javaexceptions.js b/test/script/basic/javaexceptions.js
index 3f81f697..5afc4437 100644
--- a/test/script/basic/javaexceptions.js
+++ b/test/script/basic/javaexceptions.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* Basic checks for throwing and catching java exceptions from script.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/javaimporter.js b/test/script/basic/javaimporter.js
index 42551d1a..5a198c8a 100644
--- a/test/script/basic/javaimporter.js
+++ b/test/script/basic/javaimporter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -42,7 +42,7 @@ print("js=" + map.get("js"));
print("java=" + map.get("java"));
print("cpp=" + map.get("cpp"));
-var imports2 = new JavaImporter(java.io, java.util);
+var imports2 = new JavaImporter(java.io, java.util);
with (imports2) {
print(File);
}
diff --git a/test/script/basic/javainnerclasses.js b/test/script/basic/javainnerclasses.js
index c84571d7..3038969f 100644
--- a/test/script/basic/javainnerclasses.js
+++ b/test/script/basic/javainnerclasses.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
// Do it with Java.type()
var outer = new (Java.type("jdk.nashorn.test.models.OuterClass"))("apple")
print(outer)
diff --git a/test/script/basic/javasigcall.js b/test/script/basic/javasigcall.js
index c1a2df78..14c62f84 100644
--- a/test/script/basic/javasigcall.js
+++ b/test/script/basic/javasigcall.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/jquery.js b/test/script/basic/jquery.js
index f88d94b0..646aee60 100644
--- a/test/script/basic/jquery.js
+++ b/test/script/basic/jquery.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,49 +29,49 @@
*/
var urls = [
- 'http://code.jquery.com/jquery-1.7.2.min.js',
- 'http://code.jquery.com/jquery-1.7.2.js'
- ];
-
+ 'http://code.jquery.com/jquery-1.7.2.min.js',
+ 'http://code.jquery.com/jquery-1.7.2.js'
+ ];
+
function test_jquery(url) {
-
+
//bug one repro - this should compile
function a() {
- var c;
- if (func1(zz) || (c = func2(zz)) ) {
- if (c) {
- }
- }
- return target;
+ var c;
+ if (func1(zz) || (c = func2(zz)) ) {
+ if (c) {
+ }
}
-
+ return target;
+ }
+
//bug two repro - this should compile
function b() {
- return ((v ? i : "") + "str");
+ return ((v ? i : "") + "str");
}
-
+
function checkWindow(e) {
- if (e instanceof ReferenceError && e.toString().indexOf('window') != -1) {
- return;
- }
- throw e;
+ if (e instanceof ReferenceError && e.toString().indexOf('window') != -1) {
+ return;
+ }
+ throw e;
}
-
+
var name;
-
- try {
- var split = url.split('/');
- name = split[split.length - 1];
- var path = __DIR__ + "../external/jquery/" + name;
- try {
- load(path);
- } catch (e) {
- checkWindow(e);
- }
+
+ try {
+ var split = url.split('/');
+ name = split[split.length - 1];
+ var path = __DIR__ + "../external/jquery/" + name;
+ try {
+ load(path);
} catch (e) {
- print("Unexpected exception " + e);
+ checkWindow(e);
}
-
+ } catch (e) {
+ print("Unexpected exception " + e);
+ }
+
print("done " + name);
}
diff --git a/test/script/basic/jsadapter.js b/test/script/basic/jsadapter.js
index 9fe80ad4..a5c7ec21 100644
--- a/test/script/basic/jsadapter.js
+++ b/test/script/basic/jsadapter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/jsadapterlink.js b/test/script/basic/jsadapterlink.js
index 15117b3f..ed44d61e 100644
--- a/test/script/basic/jsadapterlink.js
+++ b/test/script/basic/jsadapterlink.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/json.js b/test/script/basic/json.js
index 72391ff1..ce18146a 100644
--- a/test/script/basic/json.js
+++ b/test/script/basic/json.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -51,12 +51,12 @@ print(obj2.bar);
print(JSON.stringify(obj));
print(JSON.stringify(obj2));
-try {
+try {
JSON.parse('{ "foo" /*comment */ : 44, "bar" : "hello" }', reviver);
print("Fail!");
} catch (e) {
if (!(e instanceof SyntaxError)) {
- print("Comments are illegal in JSON. Should throw SyntaxError, not " + e);
+ print("Comments are illegal in JSON. Should throw SyntaxError, not " + e);
}
}
print("Success!");
diff --git a/test/script/basic/list.js b/test/script/basic/list.js
index 59136c0b..acbffca7 100644
--- a/test/script/basic/list.js
+++ b/test/script/basic/list.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/list.js.EXPECTED b/test/script/basic/list.js.EXPECTED
index 47f3bd4f..3e410982 100644
--- a/test/script/basic/list.js.EXPECTED
+++ b/test/script/basic/list.js.EXPECTED
@@ -10,7 +10,7 @@ bar
l[0]=foo
l[1]=a
l[0.9]=null
-l['blah']=null
+l['blah']=undefined
l[size_name]()=2
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
java.lang.IndexOutOfBoundsException: Index: Infinity, Size: 2
diff --git a/test/script/basic/literal.js b/test/script/basic/literal.js
index 2003c343..8c21091d 100644
--- a/test/script/basic/literal.js
+++ b/test/script/basic/literal.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Object literal test.
*
* @test
- * @run
+ * @run
*/
diff --git a/test/script/basic/load.js b/test/script/basic/load.js
index 4c8f9be2..7426b44b 100644
--- a/test/script/basic/load.js
+++ b/test/script/basic/load.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/loadedfile.js b/test/script/basic/loadedfile.js
index dfc09a3a..459e1225 100644
--- a/test/script/basic/loadedfile.js
+++ b/test/script/basic/loadedfile.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/localundef.js b/test/script/basic/localundef.js
index 05484928..82922ef2 100644
--- a/test/script/basic/localundef.js
+++ b/test/script/basic/localundef.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -32,7 +32,7 @@
function func(arg){
// initializing "x" with something removes VerifyError!
var x;
- if (arg == 1) {
+ if (arg == 1) {
return x;
} else {
x = 0;
diff --git a/test/script/basic/map.js b/test/script/basic/map.js
index c024f6eb..79bf3d3f 100644
--- a/test/script/basic/map.js
+++ b/test/script/basic/map.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -41,7 +41,7 @@ m.put("empty", "foo")
print("m = " + m)
print("m.empty = " + m.empty) // prints "false"
-print("m['empty'] = " + m['empty'])
+print("m['empty'] = " + m['empty'])
print("m[empty_key] = " + m[empty_key]) // prints "foo"
print("m.bwah = " + m.bwah) // prints "null"
diff --git a/test/script/basic/math.js b/test/script/basic/math.js
index d6b34c4a..2d8c2d21 100644
--- a/test/script/basic/math.js
+++ b/test/script/basic/math.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/minuszero.js b/test/script/basic/minuszero.js
index 21c1cdff..7caa9aaa 100644
--- a/test/script/basic/minuszero.js
+++ b/test/script/basic/minuszero.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/module.js b/test/script/basic/module.js
index 665e3628..af6f632e 100644
--- a/test/script/basic/module.js
+++ b/test/script/basic/module.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,4 +31,4 @@ function (exports) {
exports.func = function() {
print("module.func called");
}
-}
+}
diff --git a/test/script/basic/moduleload.js b/test/script/basic/moduleload.js
index 633d2a1c..bcabe17f 100644
--- a/test/script/basic/moduleload.js
+++ b/test/script/basic/moduleload.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/nashorn2.js b/test/script/basic/nashorn2.js
index d509a011..a8eb1446 100644
--- a/test/script/basic/nashorn2.js
+++ b/test/script/basic/nashorn2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,9 +25,9 @@
* Regression: NAS2 - lhs of index has no symbol.
*
* @test
- * @run
+ * @run
*/
-
+
var obj = { prop: [3, 4] };
print(obj.prop[0]);
diff --git a/test/script/basic/natives.js b/test/script/basic/natives.js
index 60f96104..ee7e411c 100644
--- a/test/script/basic/natives.js
+++ b/test/script/basic/natives.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
var s = "abcded";
var n = 1289.90;
var b = true;
diff --git a/test/script/basic/new.js b/test/script/basic/new.js
index 25904b1a..ec26b695 100644
--- a/test/script/basic/new.js
+++ b/test/script/basic/new.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* new Function test.
*
* @test
- * @run
+ * @run
*/
function MyObject() {
diff --git a/test/script/basic/newexpr.js b/test/script/basic/newexpr.js
index d8d1b48c..90c31171 100644
--- a/test/script/basic/newexpr.js
+++ b/test/script/basic/newexpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -44,8 +44,8 @@ function func() {
}
print(new func().foo);
-
-print ((new function() { this.x = "hello" }).x);
+
+print ((new function() { this.x = "hello" }).x);
var abc = {
bar: function() {
@@ -56,10 +56,10 @@ var abc = {
print(new abc.bar().x);
function func2() {
- return {
+ return {
foo: function() {
print("foo");
- }
+ }
};
};
diff --git a/test/script/basic/newnew.js b/test/script/basic/newnew.js
index 98a8e4db..9eaa516e 100644
--- a/test/script/basic/newnew.js
+++ b/test/script/basic/newnew.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
function myObject() {
this.x = 10;
this.y = 20;
diff --git a/test/script/basic/no_line_numbers.js b/test/script/basic/no_line_numbers.js
index bd18e4d5..f53eb512 100644
--- a/test/script/basic/no_line_numbers.js
+++ b/test/script/basic/no_line_numbers.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -53,8 +53,8 @@ for ( ; ; ) {
while (true) {
break;
- if (true) {
- var s;
+ if (true) {
+ var s;
}
}
@@ -64,20 +64,20 @@ print("u = "+u);
for ( ; ; ) {
break;
while (true) {
- do {
- var u;
- } while (true);
- }
+ do {
+ var u;
+ } while (true);
+ }
}
function terminal() {
print("r = "+r);
print("t = "+t);
for (;;) {
- var r;
- return;
- var t;
- print("THIS SHOULD NEVER BE PRINTED!");
+ var r;
+ return;
+ var t;
+ print("THIS SHOULD NEVER BE PRINTED!");
}
print("NEITHER SHOULD THIS");
}
@@ -87,13 +87,13 @@ terminal();
function terminal2() {
print("q = "+q);
for (;;) {
- return;
- print("THIS SHOULD NEVER BE PRINTED!");
+ return;
+ print("THIS SHOULD NEVER BE PRINTED!");
}
print("NEITHER SHOULD THIS");
}
-try {
+try {
terminal2();
} catch (e) {
print(e);
@@ -111,13 +111,13 @@ try {
} catch (e) {
print(e);
}
-
+
function disp_a() {
var a = 20;
print("Value of 'a' inside the function " + a);
}
-
+
var a = 10;
disp_a();
diff --git a/test/script/basic/nonconstructors.js b/test/script/basic/nonconstructors.js
index 8fb0d368..9c529db0 100644
--- a/test/script/basic/nonconstructors.js
+++ b/test/script/basic/nonconstructors.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/nosuchmethod.js b/test/script/basic/nosuchmethod.js
index 6ac03f20..6a539dc1 100644
--- a/test/script/basic/nosuchmethod.js
+++ b/test/script/basic/nosuchmethod.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Test noSuchMethod feature.
*
* @test
- * @run
+ * @run
*/
__noSuchProperty__ = function(a) { this[a] = "xxx"; return this[a]; }
diff --git a/test/script/basic/nosuchproperty.js b/test/script/basic/nosuchproperty.js
index 87976106..a414f17e 100644
--- a/test/script/basic/nosuchproperty.js
+++ b/test/script/basic/nosuchproperty.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/number.js b/test/script/basic/number.js
index 92156156..83f915c1 100644
--- a/test/script/basic/number.js
+++ b/test/script/basic/number.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/numberstring.js b/test/script/basic/numberstring.js
index 7daddb06..62b3d581 100644
--- a/test/script/basic/numberstring.js
+++ b/test/script/basic/numberstring.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/objectprops.js b/test/script/basic/objectprops.js
index 525e80cb..6f157ad6 100644
--- a/test/script/basic/objectprops.js
+++ b/test/script/basic/objectprops.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -45,7 +45,7 @@ Object.defineProperties(obj,
xyz: { value: 44 },
abc: { get: function() { print("get abc"); return "abc"; } }
}
-);
+);
print("obj.xyz = " + obj.xyz);
print("obj.abc = " + obj.abc);
@@ -54,7 +54,7 @@ function MyConstructor() {}
var obj2 = Object.create(MyConstructor.prototype);
print("obj2 in MyConstructor instance? " + (obj2 instanceof MyConstructor));
-var obj3 = Object.create(Object.prototype,
+var obj3 = Object.create(Object.prototype,
{
xyz: { value: 44 }
}
diff --git a/test/script/basic/objects.js b/test/script/basic/objects.js
index 9d913793..fd79508f 100644
--- a/test/script/basic/objects.js
+++ b/test/script/basic/objects.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/octane-payload.js b/test/script/basic/octane-payload.js
new file mode 100644
index 00000000..f2be6b12
--- /dev/null
+++ b/test/script/basic/octane-payload.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @subtest
+ */
+
+function initZlib() {
+ zlib = new BenchmarkSuite('zlib', [152815148], [
+ new Benchmark('zlib', false, true, 10,
+ runZlib, undefined, tearDownZlib, null, 3)]);
+}
+
+var tests = [
+ {name:"box2d", files:["box2d.js"], suite:"Box2DBenchmark"},
+ {name:"code-load", files:["code-load.js"], suite:"CodeLoad"},
+ {name:"crypto", files:["crypto.js"], suite:"Crypto"},
+ {name:"deltablue", files:["deltablue.js"], suite:"DeltaBlue"},
+ {name:"earley-boyer", files:["earley-boyer.js"], suite:"EarleyBoyer"},
+ {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
+ {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"},
+ {name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"},
+ {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS", cleanUpIteration: function() { canvas_logs = []; }},
+ {name:"raytrace", files:["raytrace.js"], suite:"RayTrace"},
+ {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"},
+ {name:"richards", files:["richards.js"], suite:"Richards"},
+ {name:"splay", files:["splay.js"], suite:"Splay"},
+ {name:"typescript", files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
+ //zlib currently disabled - requires read
+ {name:"zlib", files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
+];
+
+var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
+
+// TODO: why is this path hard coded when it's defined in project properties?
+var path = dir + "../external/octane/";
+var base = path + "base.js";
+
diff --git a/test/script/basic/optimistic_arithmetic_check_type.js b/test/script/basic/optimistic_arithmetic_check_type.js
new file mode 100644
index 00000000..62ff301d
--- /dev/null
+++ b/test/script/basic/optimistic_arithmetic_check_type.js
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = 3, b, c;
+var x = { a: 2, b:1, c: 7, d: -1}
+var y = { a: Number.MAX_VALUE, b: Number.POSITIVE_INFINITY, c: "Hello", d: undefined}
+
+// Testing arithmetic operators
+//-- Local variable
+print(inspect(x.a*x.b, "local int multiplication by local int"))
+print(inspect(x.a/x.b, "local int division by local int without remainder"))
+print(inspect(x.c/x.a, "local int division by local int with remainder"))
+print(inspect(x.c%x.a, "local int modulo by local int"))
+print(inspect(x.a+x.b, "local int addition local int"))
+print(inspect(x.a-x.b, "local int substraction local int"))
+print(inspect(y.a*y.a, "max value multiplication by max value"))
+print(inspect(y.b*y.b, "infinity multiplication by infinity"))
+print(inspect(x.d/y.b, "-1 division by infinity"))
+print(inspect(y.b/x.e, "infinity division by zero"))
+print(inspect(y.b/y.c, "infinity division by String"))
+print(inspect(y.d/y.d, "local undefined division by local undefined"))
+print(inspect(y.d*y.d, "local undefined multiplication by local undefined"))
+print(inspect(y.d+x.a, "local undefined addition local int"))
+print(inspect(y.d--, "local undefined decrement postfix"))
+print(inspect(--y.d, "local undefined decrement prefix"))
+print(inspect(x.a++, "local int increment postfix"))
+print(inspect(++x.a, "local int increment prefix"))
+print(inspect(x.a--, "local int decrement postfix"))
+print(inspect(--x.a, "local int decrement prefix"))
+print(inspect(+x.a, "local int unary plus"))
+print(inspect(-x.a, "local int unary minus"))
+//-- Global variable
+print(inspect(b*c, "undefined multiplication by undefined"))
+print(inspect(b/c, "undefined division by undefined"))
+print(inspect(a+a, "global int addition global int"))
+print(inspect(a-a, "global int substraction global int"))
+print(inspect(a*a, "global int multiplication by global int"))
+print(inspect(a++, "global int increment postfix"))
+print(inspect(++a, "global int increment prefix"))
+print(inspect(a--, "global int decrement postfix"))
+print(inspect(--a, "global int decrement prefix"))
+print(inspect(+a, "global int unary plus"))
+print(inspect(-a, "global int unary minus"))
+print(inspect(b--, "global undefined decrement postfix"))
+print(inspect(--b, "global undefined decrement prefix"))
+print(inspect(x, "object"))
+print(inspect(x/x, "object division by object"))
+print(inspect(x/y, "object division by object"))
diff --git a/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED b/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED
new file mode 100644
index 00000000..bce78f92
--- /dev/null
+++ b/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED
@@ -0,0 +1,38 @@
+local int multiplication by local int: int
+local int division by local int without remainder: int
+local int division by local int with remainder: double
+local int modulo by local int: int
+local int addition local int: int
+local int substraction local int: int
+max value multiplication by max value: double
+infinity multiplication by infinity: double
+-1 division by infinity: double
+infinity division by zero: double
+infinity division by String: double
+local undefined division by local undefined: double
+local undefined multiplication by local undefined: double
+local undefined addition local int: double
+local undefined decrement postfix: double
+local undefined decrement prefix: double
+local int increment postfix: int
+local int increment prefix: int
+local int decrement postfix: int
+local int decrement prefix: int
+local int unary plus: int
+local int unary minus: int
+undefined multiplication by undefined: double
+undefined division by undefined: double
+global int addition global int: int
+global int substraction global int: int
+global int multiplication by global int: int
+global int increment postfix: int
+global int increment prefix: int
+global int decrement postfix: int
+global int decrement prefix: int
+global int unary plus: int
+global int unary minus: int
+global undefined decrement postfix: double
+global undefined decrement prefix: double
+object: object
+object division by object: double
+object division by object: double \ No newline at end of file
diff --git a/test/script/basic/optimistic_assignment_check_type.js b/test/script/basic/optimistic_assignment_check_type.js
new file mode 100644
index 00000000..7ead00d8
--- /dev/null
+++ b/test/script/basic/optimistic_assignment_check_type.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = b = 3;
+var c;
+var x = { a: 2, b:1, c: 7, d: -1, e: 1}
+var y = { a: undefined, b: undefined}
+
+// Testing assignment operators
+//-- Global variable
+print(inspect(a=c, "global int assignment to global variable"))
+print(inspect(a=b, "undefined assignment to global int"))
+print(inspect(a=y.a, "global int assignment to undefined"))
+print(inspect(a+=b, "undefined addition assignment to global int"))
+print(inspect(b=b+b, "global int addition global int"))
+print(inspect(b+= y.a, "global int addition assignment undefined"))
+//--Local variable
+print(inspect(x.a+= y.a, "local int addition assignment local undefined"))
+print(inspect(x.b=y.a, "local int assignment to undefined"))
+print(inspect(y.a+=y.a, "local undefined addition assignment local undefined"))
+print(inspect(x.c-=x.d, "local int substraction assignment local int"))
+print(inspect(x.c*=x.d, "local int multiplication assignment local int"))
+print(inspect(x.c/=x.d, "local int division assignment local int"))
+print(inspect(y.b=x.c, "local undefined assignment to local int"))
+print(inspect(y.c=x.c, "local boolean assignment to local int"))
diff --git a/test/script/basic/optimistic_assignment_check_type.js.EXPECTED b/test/script/basic/optimistic_assignment_check_type.js.EXPECTED
new file mode 100644
index 00000000..4e4deeac
--- /dev/null
+++ b/test/script/basic/optimistic_assignment_check_type.js.EXPECTED
@@ -0,0 +1,14 @@
+global int assignment to global variable: undefined
+undefined assignment to global int: int
+global int assignment to undefined: undefined
+undefined addition assignment to global int: double
+global int addition global int: int
+global int addition assignment undefined: double
+local int addition assignment local undefined: double
+local int assignment to undefined: undefined
+local undefined addition assignment local undefined: double
+local int substraction assignment local int: int
+local int multiplication assignment local int: int
+local int division assignment local int: int
+local undefined assignment to local int: int
+local boolean assignment to local int: int \ No newline at end of file
diff --git a/test/script/basic/optimistic_check_type.js b/test/script/basic/optimistic_check_type.js
new file mode 100644
index 00000000..67e27c22
--- /dev/null
+++ b/test/script/basic/optimistic_check_type.js
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a=3, b=2.3, c=true, d;
+var x = { a: 2, b:0, c:undefined}
+var trees = new Array("redwood", "bay", "cedar", "oak");
+
+// Testing conditional operator
+print(inspect("" ? b : x.a, "ternary operator"))
+var b1 = b;
+print(inspect(x.b ? b1 : x.a, "ternary operator"))
+var b2 = b;
+print(inspect(c ? b2 : a, "ternary operator"))
+var b3 = b;
+print(inspect(!c ? b3 : a, "ternary operator"))
+var b4 = b;
+print(inspect(d ? b4 : x.c, "ternary operator"))
+print(inspect(x.c ? a : c, "ternary operator"))
+print(inspect(c ? d : a, "ternary operator"))
+var b5 = b;
+print(inspect(c ? +a : b5, "ternary operator"))
+
+// Testing format methods
+print(inspect(b.toFixed(2), "global double toFixed()"))
+print(inspect(b.toPrecision(2)/1, "global double toPrecision() divided by 1"))
+print(inspect(b.toExponential(2), "global double toExponential()"))
+
+// Testing arrays
+print(inspect(trees[1], "member object"))
+trees[1] = undefined;
+print(inspect(trees[1], "member undefined"))
+var b6=b;
+print(inspect(1 in trees ? b6 : a, "conditional on array member"))
+delete trees[2]
+var b7=b;
+print(inspect(2 in trees ? b7 : a, "conditional on array member"))
+print(inspect(3 in trees ? trees[2]="bay" : a, "conditional on array member"))
+var b8=b;
+print(inspect("oak" in trees ? b8 : a, "conditional on array member"))
+
+// Testing nested functions and return value
+function f1() {
+ var x = 2, y = 1;
+ function g() {
+ print(inspect(x, "outer local variable"));
+ print(inspect(a, "global variable"));
+ print(inspect(x*y, "outer local int multiplication by outer local int"));
+ print(inspect(a*d, "global int multiplication by global undefined"));
+ }
+ g()
+}
+f1()
+
+function f2(a,b,c) {
+ g = (a+b) * c;
+ print(inspect(c, "local undefined"));
+ print(inspect(a+b, "local undefined addition local undefined"));
+ print(inspect(g, "local undefined multiplication by undefined"));
+}
+f2()
+
+function f3(a,b) {
+ g = a && b;
+ print(inspect(g, "local undefined AND local undefined"));
+ print(inspect(c||g, "global true OR local undefined"));
+}
+f3()
+
+function f4() {
+ var x = true, y = 0;
+ function g() {
+ print(inspect(x+y, "outer local true addition local int"));
+ print(inspect(a+x, "global int addition outer local true"));
+ print(inspect(x*y, "outer local true multiplication by outer local int"));
+ print(inspect(y*d, "outer local int multiplication by global undefined"));
+ }
+ g()
+}
+f4()
diff --git a/test/script/basic/optimistic_check_type.js.EXPECTED b/test/script/basic/optimistic_check_type.js.EXPECTED
new file mode 100644
index 00000000..b1ae8004
--- /dev/null
+++ b/test/script/basic/optimistic_check_type.js.EXPECTED
@@ -0,0 +1,30 @@
+ternary operator: int
+ternary operator: int
+ternary operator: double
+ternary operator: int
+ternary operator: undefined
+ternary operator: boolean
+ternary operator: undefined
+ternary operator: int
+global double toFixed(): object
+global double toPrecision() divided by 1: double
+global double toExponential(): object
+member object: object
+member undefined: undefined
+conditional on array member: double
+conditional on array member: int
+conditional on array member: object
+conditional on array member: int
+outer local variable: int
+global variable: int
+outer local int multiplication by outer local int: int
+global int multiplication by global undefined: double
+local undefined: undefined
+local undefined addition local undefined: double
+local undefined multiplication by undefined: double
+local undefined AND local undefined: undefined
+global true OR local undefined: boolean
+outer local true addition local int: double
+global int addition outer local true: double
+outer local true multiplication by outer local int: double
+outer local int multiplication by global undefined: double
diff --git a/test/script/basic/optimistic_logical_check_type.js b/test/script/basic/optimistic_logical_check_type.js
new file mode 100644
index 00000000..bb9de0c8
--- /dev/null
+++ b/test/script/basic/optimistic_logical_check_type.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = 3, b = true, c = 0;
+var x = { a: 2, b: undefined, c: true}
+
+// Testing logical operators
+//-- Global variable
+print(inspect("cat" && "dog", "object AND object"))
+print(inspect(b && a, "true AND non-falsey global int"))
+print(inspect(a && b, "non-falsey global int AND true"))
+print(inspect(x && b, "non-falsey object AND true"))
+print(inspect(b && x, "true AND non-falsey object"))
+print(inspect("cat" || "dog", "object OR object"))
+print(inspect(b || a, "true OR non-falsey global int"))
+print(inspect(a || b, "non-falsey global int OR true"))
+print(inspect(x || b, "non-falsey object OR true"))
+print(inspect(b || x, "true OR non-falsey object"))
+print(inspect(!x.c || b, "false OR true"))
+print(inspect(c && b, "falsey global int AND true"))
+print(inspect(c || x.b, "falsey global int OR undefined"))
+print(inspect(!c || x.b, "logical not falsey global int OR undefined"))
+print(inspect(!b || x.b, "false OR undefined"))
+print(inspect(!b || c, "false OR falsey global int"))
+print(inspect(!c || c, "logical not falsey global int OR falsey global int"))
+ //--Local variable
+print(inspect(x.b && a, "local undefined AND non-falsey global int"))
+print(inspect(b && x.b, "true AND local undefined"))
+print(inspect(x.b && x.a, "local undefined AND non-falsey local int"))
+print(inspect(x.b || b, "local undefined OR true"))
+print(inspect(b || x.b, "true OR local undefined"))
+print(inspect(x.a && x.c, "non-falsey local int AND true"))
+print(inspect(x.c && x.a, "true AND non-falsey local int"))
+print(inspect(x.c && !!x.a, "true AND double logical not non-falsey local int "))
+print(inspect(!x.c && x.a, "false AND non-falsey local int"))
+print(inspect(x.a || x.c, "non-falsey local int OR true"))
+print(inspect(!x.c || x.c, "false OR true"))
diff --git a/test/script/basic/optimistic_logical_check_type.js.EXPECTED b/test/script/basic/optimistic_logical_check_type.js.EXPECTED
new file mode 100644
index 00000000..994b0832
--- /dev/null
+++ b/test/script/basic/optimistic_logical_check_type.js.EXPECTED
@@ -0,0 +1,28 @@
+object AND object: object
+true AND non-falsey global int: int
+non-falsey global int AND true: boolean
+non-falsey object AND true: boolean
+true AND non-falsey object: object
+object OR object: object
+true OR non-falsey global int: boolean
+non-falsey global int OR true: int
+non-falsey object OR true: object
+true OR non-falsey object: boolean
+false OR true: boolean
+falsey global int AND true: int
+falsey global int OR undefined: undefined
+logical not falsey global int OR undefined: boolean
+false OR undefined: undefined
+false OR falsey global int: int
+logical not falsey global int OR falsey global int: boolean
+local undefined AND non-falsey global int: undefined
+true AND local undefined: undefined
+local undefined AND non-falsey local int: undefined
+local undefined OR true: boolean
+true OR local undefined: boolean
+non-falsey local int AND true: boolean
+true AND non-falsey local int: int
+true AND double logical not non-falsey local int : boolean
+false AND non-falsey local int: boolean
+non-falsey local int OR true: int
+false OR true: boolean
diff --git a/test/script/basic/options.js b/test/script/basic/options.js
index 102bb5ec..b97aed03 100644
--- a/test/script/basic/options.js
+++ b/test/script/basic/options.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/paramspec.js b/test/script/basic/paramspec.js
index c0ea2a54..625c9725 100644
--- a/test/script/basic/paramspec.js
+++ b/test/script/basic/paramspec.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/assignmentExpr.js b/test/script/basic/parser/assignmentExpr.js
index 231e19fd..e5b5641d 100644
--- a/test/script/basic/parser/assignmentExpr.js
+++ b/test/script/basic/parser/assignmentExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/binaryExpr.js b/test/script/basic/parser/binaryExpr.js
index a2b761da..b5e62768 100644
--- a/test/script/basic/parser/binaryExpr.js
+++ b/test/script/basic/parser/binaryExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/breakStat.js b/test/script/basic/parser/breakStat.js
index 1b16cc2c..3b2b0294 100644
--- a/test/script/basic/parser/breakStat.js
+++ b/test/script/basic/parser/breakStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/breakStat.js.EXPECTED b/test/script/basic/parser/breakStat.js.EXPECTED
index 1d9fd079..f9a7db96 100644
--- a/test/script/basic/parser/breakStat.js.EXPECTED
+++ b/test/script/basic/parser/breakStat.js.EXPECTED
@@ -24,10 +24,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "loop"
- },
+ "label": "loop",
"body": {
"type": "BlockStatement",
"body": [
@@ -42,10 +39,7 @@
"body": [
{
"type": "BreakStatement",
- "label": {
- "type": "Identifier",
- "name": "loop"
- }
+ "label": "loop"
}
]
}
@@ -60,10 +54,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "loop"
- },
+ "label": "loop",
"body": {
"type": "BlockStatement",
"body": [
@@ -77,10 +68,7 @@
"body": [
{
"type": "BreakStatement",
- "label": {
- "type": "Identifier",
- "name": "loop"
- }
+ "label": "loop"
}
]
}
diff --git a/test/script/basic/parser/condExpr.js b/test/script/basic/parser/condExpr.js
index 3644ff35..f9c59fce 100644
--- a/test/script/basic/parser/condExpr.js
+++ b/test/script/basic/parser/condExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/continueStat.js b/test/script/basic/parser/continueStat.js
index 22ddadd4..8a715bee 100644
--- a/test/script/basic/parser/continueStat.js
+++ b/test/script/basic/parser/continueStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/continueStat.js.EXPECTED b/test/script/basic/parser/continueStat.js.EXPECTED
index cfd3114d..efa51d98 100644
--- a/test/script/basic/parser/continueStat.js.EXPECTED
+++ b/test/script/basic/parser/continueStat.js.EXPECTED
@@ -24,10 +24,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- },
+ "label": "begin",
"body": {
"type": "BlockStatement",
"body": [
@@ -42,10 +39,7 @@
"body": [
{
"type": "ContinueStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- }
+ "label": "begin"
}
]
}
@@ -60,10 +54,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "start"
- },
+ "label": "start",
"body": {
"type": "BlockStatement",
"body": [
@@ -77,10 +68,7 @@
"body": [
{
"type": "ContinueStatement",
- "label": {
- "type": "Identifier",
- "name": "start"
- }
+ "label": "start"
}
]
}
diff --git a/test/script/basic/parser/debuggerStat.js b/test/script/basic/parser/debuggerStat.js
index 60eab78f..4edcf340 100644
--- a/test/script/basic/parser/debuggerStat.js
+++ b/test/script/basic/parser/debuggerStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/functions.js b/test/script/basic/parser/functions.js
index 7b624b55..93e3727b 100644
--- a/test/script/basic/parser/functions.js
+++ b/test/script/basic/parser/functions.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/ifStat.js b/test/script/basic/parser/ifStat.js
index 5d156668..7664167d 100644
--- a/test/script/basic/parser/ifStat.js
+++ b/test/script/basic/parser/ifStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/labelledStat.js b/test/script/basic/parser/labelledStat.js
index 25829a4a..2a087291 100644
--- a/test/script/basic/parser/labelledStat.js
+++ b/test/script/basic/parser/labelledStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/labelledStat.js.EXPECTED b/test/script/basic/parser/labelledStat.js.EXPECTED
index fc5f37e8..ca125dce 100644
--- a/test/script/basic/parser/labelledStat.js.EXPECTED
+++ b/test/script/basic/parser/labelledStat.js.EXPECTED
@@ -3,10 +3,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- },
+ "label": "begin",
"body": {
"type": "BlockStatement",
"body": [
@@ -20,10 +17,7 @@
"body": [
{
"type": "BreakStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- }
+ "label": "begin"
}
]
}
@@ -38,10 +32,7 @@
"body": [
{
"type": "LabeledStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- },
+ "label": "begin",
"body": {
"type": "BlockStatement",
"body": [
@@ -56,10 +47,7 @@
"body": [
{
"type": "BreakStatement",
- "label": {
- "type": "Identifier",
- "name": "begin"
- }
+ "label": "begin"
}
]
}
diff --git a/test/script/basic/parser/lhsExpr.js b/test/script/basic/parser/lhsExpr.js
index 68f4d6c3..24d5c7fe 100644
--- a/test/script/basic/parser/lhsExpr.js
+++ b/test/script/basic/parser/lhsExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/lhsExpr.js.EXPECTED b/test/script/basic/parser/lhsExpr.js.EXPECTED
index e61c6c8f..692791c0 100644
--- a/test/script/basic/parser/lhsExpr.js.EXPECTED
+++ b/test/script/basic/parser/lhsExpr.js.EXPECTED
@@ -69,10 +69,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "foo"
- },
+ "property": "foo",
"computed": false
}
}
@@ -91,16 +88,10 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "foo"
- },
+ "property": "foo",
"computed": false
},
- "property": {
- "type": "Identifier",
- "name": "bar"
- },
+ "property": "bar",
"computed": false
}
}
@@ -176,10 +167,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "Type"
- },
+ "property": "Type",
"computed": false
},
"arguments": []
@@ -200,10 +188,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "Type"
- },
+ "property": "Type",
"computed": false
},
"arguments": []
@@ -224,10 +209,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "Type"
- },
+ "property": "Type",
"computed": false
},
"arguments": [
@@ -273,10 +255,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "foo"
- },
+ "property": "foo",
"computed": false
},
"arguments": []
@@ -322,10 +301,7 @@
"type": "Identifier",
"name": "obj"
},
- "property": {
- "type": "Identifier",
- "name": "foo"
- },
+ "property": "foo",
"computed": false
},
"arguments": [
diff --git a/test/script/basic/parser/loopStat.js b/test/script/basic/parser/loopStat.js
index ba705568..99c30744 100644
--- a/test/script/basic/parser/loopStat.js
+++ b/test/script/basic/parser/loopStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/objectLitExpr.js b/test/script/basic/parser/objectLitExpr.js
index bdecc7fa..394a64c9 100644
--- a/test/script/basic/parser/objectLitExpr.js
+++ b/test/script/basic/parser/objectLitExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/parenExpr.js b/test/script/basic/parser/parenExpr.js
index 2d52a023..ceaaa365 100644
--- a/test/script/basic/parser/parenExpr.js
+++ b/test/script/basic/parser/parenExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/primaryExpr.js b/test/script/basic/parser/primaryExpr.js
index 950c47f3..6a543bfa 100644
--- a/test/script/basic/parser/primaryExpr.js
+++ b/test/script/basic/parser/primaryExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/returnStat.js b/test/script/basic/parser/returnStat.js
index 741a2340..f143c402 100644
--- a/test/script/basic/parser/returnStat.js
+++ b/test/script/basic/parser/returnStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/switchStat.js b/test/script/basic/parser/switchStat.js
index 6f0dd75e..f62a5256 100644
--- a/test/script/basic/parser/switchStat.js
+++ b/test/script/basic/parser/switchStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/throwStat.js b/test/script/basic/parser/throwStat.js
index 345e3b8c..18a3533d 100644
--- a/test/script/basic/parser/throwStat.js
+++ b/test/script/basic/parser/throwStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/tryCatchStat.js b/test/script/basic/parser/tryCatchStat.js
index de153133..15919bde 100644
--- a/test/script/basic/parser/tryCatchStat.js
+++ b/test/script/basic/parser/tryCatchStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/unaryExpr.js b/test/script/basic/parser/unaryExpr.js
index e21b55f3..d739bd54 100644
--- a/test/script/basic/parser/unaryExpr.js
+++ b/test/script/basic/parser/unaryExpr.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/useStrict.js b/test/script/basic/parser/useStrict.js
index 4d1c7a94..143eac96 100644
--- a/test/script/basic/parser/useStrict.js
+++ b/test/script/basic/parser/useStrict.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/util.js b/test/script/basic/parser/util.js
index 6170018b..ce417d09 100644
--- a/test/script/basic/parser/util.js
+++ b/test/script/basic/parser/util.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/varDecl.js b/test/script/basic/parser/varDecl.js
index e505761b..6f7b8ed6 100644
--- a/test/script/basic/parser/varDecl.js
+++ b/test/script/basic/parser/varDecl.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/parser/withStat.js b/test/script/basic/parser/withStat.js
index 3f94c7f5..c1d7d305 100644
--- a/test/script/basic/parser/withStat.js
+++ b/test/script/basic/parser/withStat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/propchange.js b/test/script/basic/propchange.js
index b3170327..66d465e7 100644
--- a/test/script/basic/propchange.js
+++ b/test/script/basic/propchange.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -26,7 +26,7 @@
*
* @test
* @run
- */
+ */
var obj = { x: 343 };
diff --git a/test/script/basic/propertycheck.js b/test/script/basic/propertycheck.js
index 8e35015f..61352c1b 100644
--- a/test/script/basic/propertycheck.js
+++ b/test/script/basic/propertycheck.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/prototype.js b/test/script/basic/prototype.js
index e85d3d4a..ede550ef 100644
--- a/test/script/basic/prototype.js
+++ b/test/script/basic/prototype.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,12 +30,12 @@
function check(url_) {
try {
- load(url_);
+ load(url_);
} catch (e) {
- if (e instanceof ReferenceError && e.toString().indexOf('navigator') != -1) {
- return;
- }
- throw e;
+ if (e instanceof ReferenceError && e.toString().indexOf('navigator') != -1) {
+ return;
+ }
+ throw e;
}
}
@@ -43,7 +43,7 @@ var file = __DIR__ + "../external/prototype/prototype.js";
try {
try {
check(file);
- } catch (e) {
+ } catch (e) {
print(e);
}
} catch (e) {
diff --git a/test/script/basic/pushpull.js b/test/script/basic/pushpull.js
index 192ef9cb..a57d362c 100644
--- a/test/script/basic/pushpull.js
+++ b/test/script/basic/pushpull.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/ranges_disabled.js.EXPECTED b/test/script/basic/ranges_disabled.js.EXPECTED
deleted file mode 100644
index 1a99c91b..00000000
--- a/test/script/basic/ranges_disabled.js.EXPECTED
+++ /dev/null
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
diff --git a/test/script/basic/ranges_enabled.js.EXPECTED b/test/script/basic/ranges_enabled.js.EXPECTED
deleted file mode 100644
index 1a99c91b..00000000
--- a/test/script/basic/ranges_enabled.js.EXPECTED
+++ /dev/null
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
diff --git a/test/script/basic/regex.js b/test/script/basic/regex.js
index 49dd7434..198c254b 100644
--- a/test/script/basic/regex.js
+++ b/test/script/basic/regex.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,9 +25,9 @@
* RegExp test.
*
* @test
- * @run
+ * @run
*/
-
+
var regexp;
regexp = new RegExp("dog");
diff --git a/test/script/basic/regexp_flags.js b/test/script/basic/regexp_flags.js
index 9ff7543f..05cbc2ac 100644
--- a/test/script/basic/regexp_flags.js
+++ b/test/script/basic/regexp_flags.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,7 +24,7 @@
/**
* NASHORN-154: Early error reporting.
*
- * Errors in regular expression literals that are not implementation-defined
+ * Errors in regular expression literals that are not implementation-defined
* syntax extensions.
*
* @test
diff --git a/test/script/basic/ranges_enabled.js b/test/script/basic/relink_index_getter.js
index 45d9efb0..9cd06965 100644
--- a/test/script/basic/ranges_enabled.js
+++ b/test/script/basic/relink_index_getter.js
@@ -1,33 +1,33 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
+ * relink_index_getter: after call site was linked for array, make sure it
+ * gets correctly relinked for boolean.
*
* @test
- * @option --range-analysis
- * @run
+ * @run
*/
-load(__DIR__ + "ranges_payload.js");
+var x = [[], false]
+for(var i in x) { print(x[i][0]) }
diff --git a/test/script/basic/relink_index_getter.js.EXPECTED b/test/script/basic/relink_index_getter.js.EXPECTED
new file mode 100644
index 00000000..d4f80bf8
--- /dev/null
+++ b/test/script/basic/relink_index_getter.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined
+undefined
diff --git a/test/script/basic/run-octane.js b/test/script/basic/run-octane.js
index 840f07b7..a0a9bdc8 100644
--- a/test/script/basic/run-octane.js
+++ b/test/script/basic/run-octane.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,31 +24,10 @@
/**
* @subtest
*/
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "octane-payload.js");
-var tests = [
- {name:"box2d", files:["box2d.js"], suite:"Box2DBenchmark"},
- {name:"code-load", files:["code-load.js"], suite:"CodeLoad"},
- {name:"crypto", files:["crypto.js"], suite:"Crypto"},
- {name:"deltablue", files:["deltablue.js"], suite:"DeltaBlue"},
- {name:"earley-boyer", files:["earley-boyer.js"], suite:"EarleyBoyer"},
- {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
- {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"},
- {name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"},
- {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS"},
- {name:"raytrace", files:["raytrace.js"], suite:"RayTrace"},
- {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"},
- {name:"richards", files:["richards.js"], suite:"Richards"},
- {name:"splay", files:["splay.js"], suite:"Splay"},
- {name:"typescript", files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"}
- //zlib currently disabled - requires read
- // {name:"zlib", files:["zlib.js", "zlib-data.js"], suite:"zlib"},
-];
-var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
-
-// TODO: why is this path hard coded when it's defined in project properties?
-var path = dir + "../external/octane/";
-
-var runtime = "";
+var runtime = undefined;
var verbose = false;
var numberOfIterations = 5;
@@ -64,145 +43,159 @@ function should_compile_only(name) {
function load_bench(arg) {
for (var idx = 0; idx < arg.files.length; idx++) {
- var f = arg.files[idx];
- var file = f.split('/');
- var file_name = path + file[file.length - 1];
-
- var compile_and_return = should_compile_only(file_name);
- if (compile_and_return) {
- if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
- return true;
- }
- }
-
- print_verbose(arg, "loading '" + arg.name + "' [" + f + "]...");
- load(file_name);
+ var f = arg.files[idx];
+ var file = f.split('/');
+ var file_name = path + file[file.length - 1];
+
+ var compile_and_return = should_compile_only(file_name);
+ if (compile_and_return) {
+ if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
+ return true;
+ }
+ }
+
+ print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name);
+ load(file_name);
+ }
+
+ if (typeof arg.before !== 'undefined') {
+ arg.before();
}
if (compile_and_return) {
- print_always(arg, "Compiled OK");
+ print_always(arg, "Compiled OK");
}
return !compile_and_return;
}
+
function run_one_benchmark(arg, iters) {
if (!load_bench(arg)) {
- return;
- }
-
+ return;
+ }
+
var success = true;
var current_name;
-
+
if (iters == undefined) {
- iters = numberOfIterations;
+ iters = numberOfIterations;
} else {
- numberOfIterations = iters;
+ numberOfIterations = iters;
}
-
+
var benchmarks = eval(arg.suite + ".benchmarks");
var min_score = 1e9;
var max_score = 0;
var mean_score = 0;
try {
- for (var x = 0; x < benchmarks.length ; x++) {
- //do warmup run
- //reset random number generator needed as of octane 9 before each run
- BenchmarkSuite.ResetRNG();
- benchmarks[x].Setup();
- }
- BenchmarkSuite.ResetRNG();
- print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds (" + runtime + ")");
-
- var scores = [];
-
- var min_time_ms = min_time * 1000;
- var len = benchmarks.length;
-
- for (var it = 0; it < iters + 1; it++) {
- //every iteration must take a minimum of 10 secs
- var ops = 0;
- var elapsed = 0;
- var start = new Date;
- do {
- for (var i = 0; i < len; i++) {
- benchmarks[i].run();
- //important - no timing here like elapsed = new Date() - start, as in the
- //original harness. This will make timing very non-deterministic.
- //NOTHING else must live in this loop
- }
- ops += len;
- elapsed = new Date - start;
- } while (elapsed < min_time * 1000);
-
- var score = ops / elapsed * 1000 * 60;
- scores.push(score);
- var name = it == 0 ? "warmup" : "iteration " + it;
- print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
- }
-
- for (var x = 0; x < benchmarks.length ; x++) {
- benchmarks[x].TearDown();
- }
-
- for (var x = 1; x < iters + 1 ; x++) {
- mean_score += scores[x];
- min_score = Math.min(min_score, scores[x]);
- max_score = Math.max(max_score, scores[x]);
- }
- mean_score /= iters;
-
+ for (var x = 0; x < benchmarks.length ; x++) {
+ //do warmup run
+ //reset random number generator needed as of octane 9 before each run
+ BenchmarkSuite.ResetRNG();
+ benchmarks[x].Setup();
+ }
+ BenchmarkSuite.ResetRNG();
+ print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
+
+ var scores = [];
+
+ var min_time_ms = min_time * 1000;
+ var len = benchmarks.length;
+
+ for (var it = 0; it < iters + 1; it++) {
+ //every iteration must take a minimum of 10 secs
+ var ops = 0;
+ var elapsed = 0;
+ var start = new Date;
+ do {
+ for (var i = 0; i < len; i++) {
+ benchmarks[i].run();
+ //important - no timing here like elapsed = new Date() - start, as in the
+ //original harness. This will make timing very non-deterministic.
+ //NOTHING else must live in this loop
+ }
+ ops += len;
+ elapsed = new Date - start;
+ } while (elapsed < min_time * 1000);
+
+ var score = ops / elapsed * 1000 * 60;
+ scores.push(score);
+ var name = it == 0 ? "warmup" : "iteration " + it;
+ print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
+
+ // optional per-iteration cleanup hook
+ if (typeof arg.cleanUpIteration == "function") {
+ arg.cleanUpIteration();
+ }
+ }
+
+ for (var x = 0; x < benchmarks.length ; x++) {
+ benchmarks[x].TearDown();
+ }
+
+ for (var x = 1; x < iters + 1 ; x++) {
+ mean_score += scores[x];
+ min_score = Math.min(min_score, scores[x]);
+ max_score = Math.max(max_score, scores[x]);
+ }
+ mean_score /= iters;
} catch (e) {
- print_always("*** Aborted and setting score to zero. Reason: " + e);
- mean_score = min_score = max_score = 0;
- scores = [0];
+ print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
+ if (is_this_nashorn() && e instanceof java.lang.Throwable) {
+ e.printStackTrace();
+ }
+ mean_score = min_score = max_score = 0;
+ scores = [0];
}
var res = mean_score.toFixed(0);
if (verbose) {
- res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
+ res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
}
print_always(arg, res);
}
+function runtime_string() {
+ return runtime == undefined ? "" : ("[" + runtime + "] ");
+}
+
function print_always(arg, x) {
- print("[" + arg.name + "] " + x);
+ print(runtime_string() + "[" + arg.name + "] " + x);
}
function print_verbose(arg, x) {
if (verbose) {
- print_always(arg, x)
+ print_always(arg, x)
}
}
function run_suite(tests, iters) {
for (var idx = 0; idx < tests.length; idx++) {
- run_one_benchmark(tests[idx], iters);
+ run_one_benchmark(tests[idx], iters);
}
}
-runtime = "command line";
-
var args = [];
if (typeof $ARGS !== 'undefined') {
args = $ARGS;
} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
args = arguments;
-}
+}
var new_args = [];
for (i in args) {
if (args[i].toString().indexOf(' ') != -1) {
- args[i] = args[i].replace(/\/$/, '');
- var s = args[i].split(' ');
- for (j in s) {
- new_args.push(s[j]);
- }
+ args[i] = args[i].replace(/\/$/, '');
+ var s = args[i].split(' ');
+ for (j in s) {
+ new_args.push(s[j]);
+ }
} else {
- new_args.push(args[i]);
+ new_args.push(args[i]);
}
}
@@ -214,50 +207,76 @@ var tests_found = [];
var iters = undefined;
var min_time = 5;
-for (var i = 0; i < args.length; i++) {
+for (var i = 0; i < args.length; i++) {
arg = args[i];
if (arg == "--iterations") {
- iters = +args[++i];
+ iters = +args[++i];
+ if (isNaN(iters)) {
+ throw "'--iterations' must be followed by integer";
+ }
} else if (arg == "--runtime") {
- runtime = args[++i];
+ runtime = args[++i];
} else if (arg == "--verbose") {
- verbose = true;
+ verbose = true;
} else if (arg == "--min-time") {
- min_time = +args[++i];
+ min_time = +args[++i];
+ if (isNaN(iters)) {
+ throw "'--min-time' must be followed by integer";
+ }
} else if (arg == "") {
- continue; //skip
+ continue; //skip
} else {
- var found = false;
- for (j in tests) {
- if (tests[j].name === arg) {
- tests_found.push(tests[j]);
- found = true;
- break;
- }
- }
- if (!found) {
- var str = "unknown test name: '" + arg + "' -- valid names are: ";
- for (j in tests) {
- if (j != 0) {
- str += ", ";
- }
- str += "'" + tests[j].name + "'";
- }
- throw str;
- }
+ var found = false;
+ for (j in tests) {
+ if (tests[j].name === arg) {
+ tests_found.push(tests[j]);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ var str = "unknown test name: '" + arg + "' -- valid names are: ";
+ for (j in tests) {
+ if (j != 0) {
+ str += ", ";
+ }
+ str += "'" + tests[j].name + "'";
+ }
+ throw str;
+ }
}
}
-if (tests_found.length == 0) {
+if (tests_found.length == 0) {
for (i in tests) {
- tests_found.push(tests[i]);
+ tests_found.push(tests[i]);
}
-}
-
-tests_found.sort();
+}
-load(path + 'base.js');
-run_suite(tests_found, iters);
+// returns false for rhino, v8 and all other javascript runtimes, true for Nashorn
+function is_this_nashorn() {
+ return typeof Error.dumpStack == 'function'
+}
+if (is_this_nashorn()) {
+ try {
+ read = readFully;
+ } catch (e) {
+ print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
+ throw e;
+ }
+}
+// run tests in alphabetical order by name
+tests_found.sort(function(a, b) {
+ if (a.name < b.name) {
+ return -1;
+ } else if (a.name > b.name) {
+ return 1;
+ } else {
+ return 0;
+ }
+});
+load(path + 'base.js');
+run_suite(tests_found, iters);
diff --git a/test/script/basic/runsunspider.js b/test/script/basic/runsunspider.js
index 84ce915c..738aea06 100644
--- a/test/script/basic/runsunspider.js
+++ b/test/script/basic/runsunspider.js
@@ -24,7 +24,9 @@
/**
* runsunspider : runs the sunspider tests and checks for compliance
*
- * @subtest
+ * @test
+ * @option -timezone=PST
+ * @runif external.sunspider
*/
/**
@@ -37,32 +39,32 @@ function assertEq(a, b) {
}
}
+function pprint(x) {
+ if (verbose_run) {
+ print(x);
+ }
+}
+
var runs = 0;
-var iterations__ = 1;
var total_time = 0;
function runbench(name) {
var filename = name.split("/").pop();
- if (verbose_run) {
- print("Running " + filename);
- }
+ pprint("Running (warmup/sanity) " + filename);
var start = new Date;
- for (var i = 0; i < iterations__; i++) {
- load(name);
- }
+ load(name);
+
var stop = new Date - start;
total_time += stop;
- if (verbose_run) {
- print(filename + " done in " + stop + " ms");
- }
+ pprint(filename + " done in " + stop + " ms");
runs++;
}
-var m_w = 4711;
-var m_z = 17;
-var MAXINT = 0x7fffffff;
+var m_w;
+var m_z;
+var MAXINT;
//produce deterministic random numbers for test suite
function pseudorandom() {
@@ -71,25 +73,133 @@ function pseudorandom() {
return (Math.abs((m_z << 16) + m_w) & MAXINT) / MAXINT;
}
-function runsuite(tests) {
- var changed = false;
+function initrandom() {
+ m_w = 4711;
+ m_z = 17;
+ MAXINT = 0x7fffffff;
+ Math.random = pseudorandom;
+}
+
+var rtimes = 0;
+var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
+var single;
+var verbose_run = false;
+var runall = false;
+
+var args = [];
+if (typeof $ARGS !== 'undefined') {
+ args = $ARGS;
+} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
+ args = arguments;
+}
+for (var i = 0; i < args.length; i++) {
+ if (args[i] === '--verbose') {
+ verbose_run = true;
+ } else if (args[i] === '--times') {
+ i++;
+ rtimes = +args[i];
+ } else if (args[i] === '--single') {
+ i++;
+ single = args[i];
+ } else if (args[i] === '--runall') {
+ i++;
+ runall = true;
+ }
+}
+
+function runsuite(tests) {
+ var changed = false;
+ var res = [];
var oldRandom = Math.random;
- Math.random = pseudorandom;
try {
- for (var n = 0; n < tests.length; n++) {
- path = dir + '../external/sunspider/tests/sunspider-1.0/' + tests[n].name
- runbench(path);
- if (typeof tests[n].actual !== 'undefined') {
- assertEq(tests[n].actual(), tests[n].expected());
+ for (var n = 0; n < tests.length; n++) {
+ try {
+ path = dir + '../external/sunspider/tests/sunspider-1.0.2/' + tests[n].name
+
+ initrandom();
+
+ var dd = new Date;
+
+ runbench(path);
+ if (typeof tests[n].actual !== 'undefined') {
+ assertEq(tests[n].actual(), tests[n].expected());
+ }
+
+ var times = 0;
+ if (typeof tests[n].rerun !== 'undefined' && tests[n].times > 0) {
+ pprint("rerunning " + tests[n].name + " " + tests[n].times + " times...");
+ var to = tests[n].times;
+
+ var elemsPerPercent = to / 100;
+ var po = 0|(to / 10);
+
+ pprint("Doing warmup.");
+ for (times = 0; times < to; times++) {
+ initrandom();
+ tests[n].rerun();
+ }
+
+ pprint("Doing hot runs.");
+ for (times = 0; times < to; times++) {
+ initrandom();
+ tests[n].rerun();
+ if ((times % (po|0)) == 0) {
+ pprint("\t" + times/to * 100 + "%");
+ }
+ }
+ }
+
+ var t = Math.round(((new Date - dd) / (times == 0 ? 1 : times)) * 100 / 100);
+ pprint("time per iteration: " + t + " ms");
+ if (typeof tests[n].actual !== 'undefined') {
+ assertEq(tests[n].actual(), tests[n].expected());
+ }
+ res.push(t);
+
+ pprint("");
+
+ changed = true;
+ } catch(e) {
+ if (runall) {
+ print("FAIL!");
+ } else {
+ throw e;
+ }
}
- changed = true;
}
+ } catch (e) {
+ print("FAIL!");
+ throw e;
// no scripting or something, silently fail
} finally {
- }
Math.random = oldRandom;
+ }
+
+ for (var n = 0; n < tests.length; n++) {
+
+ var time = "" + res[n];
+ while (time.length < 6) {
+ time = " " + time;
+ }
+ time += " ms";
+ if (res[n] == -1) {
+ time = "<couldn't be rerun>";
+ }
+ var str = tests[n].name;
+ for (var spaces = str.length; spaces < 32; spaces++) {
+ str += " ";
+ }
+ str += " ";
+ str += time;
+
+ if (tests[n].times > 0) {
+ str += " [";
+ str += tests[n].times + " reruns]";
+ }
+ pprint(str);
+ }
return changed;
}
@@ -106,20 +216,47 @@ function hash(str) {
}
var tests = [
- { name: 'string-base64.js',
+
+ { name: 'regexp-dna.js',
actual: function() {
- return hash(str);
+ return dnaOutputString + dnaInput;
},
expected: function() {
- return 1544571068;
- }
+ return expectedDNAOutputString + expectedDNAInput;
+ },
},
- { name: 'string-validate-input.js',
+
+ { name: 'string-base64.js',
actual: function() {
- return hash(endResult);
+ return hash(str);
},
expected: function() {
- return 2016572373;
+ return 1544571068;
+ },
+ times: rtimes,
+ rerun: function() {
+ toBinaryTable = [
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
+ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+ ];
+ var str = "";
+ for (var i = 0; i < 8192; i++)
+ str += String.fromCharCode((25 * Math.random()) + 97);
+
+ for (var i = 8192; i <= 16384; i *= 2) {
+ var base64;
+ base64 = toBase64(str);
+ var encoded = base64ToString(base64);
+
+ str += str;
+ }
+ toBinaryTable = null;
}
},
{ name: 'date-format-xparb.js',
@@ -128,7 +265,29 @@ var tests = [
},
expected: function() {
return "2017-09-05Tuesday, September 05, 2017 8:43:48 AM";
+ },
+ times: rtimes,
+ rerun: function() {
+ date = new Date("1/1/2007 1:11:11");
+ for (i = 0; i < 4000; ++i) {
+ var shortFormat = date.dateFormat("Y-m-d");
+ var longFormat = date.dateFormat("l, F d, Y g:i:s A");
+ date.setTime(date.getTime() + 84266956);
}
+ }
+
+ },
+ { name: 'string-validate-input.js',
+ actual: function() {
+ return hash(endResult);
+ },
+ expected: function() {
+ return 726038055;
+ },
+ times: rtimes,
+ rerun: function() {
+ doTest();
+ },
},
{ name: '3d-morph.js',
actual: function() {
@@ -137,6 +296,20 @@ var tests = [
},
expected: function() {
return true;
+ },
+ times: rtimes,
+ rerun: function() {
+ a = Array()
+ for (var i=0; i < nx*nz*3; ++i)
+ a[i] = 0
+ for (var i = 0; i < loops; ++i) {
+ morph(a, i/loops)
+ }
+ testOutput = 0;
+ for (var i = 0; i < nx; i++)
+ testOutput += a[3*(i*nx+i)+1];
+ a = null;
+
}
},
{ name: 'crypto-aes.js',
@@ -145,6 +318,12 @@ var tests = [
},
expected: function() {
return decryptedText;
+ },
+ times: rtimes,
+ rerun: function() {
+ cipherText = AESEncryptCtr(plainText, password, 256);
+ decryptedText = AESDecryptCtr(cipherText, password, 256);
+
}
},
{ name: 'crypto-md5.js',
@@ -153,32 +332,56 @@ var tests = [
},
expected: function() {
return "a831e91e0f70eddcb70dc61c6f82f6cd";
+ },
+ times: rtimes,
+ rerun: function() {
+ md5Output = hex_md5(plainText);
}
},
+
{ name: 'crypto-sha1.js',
actual: function() {
return sha1Output;
},
expected: function() {
return "2524d264def74cce2498bf112bedf00e6c0b796d";
+ },
+ times: rtimes,
+ rerun: function() {
+ sha1Output = hex_sha1(plainText);
}
},
+
{ name: 'bitops-bitwise-and.js',
actual: function() {
return result;
},
expected: function() {
return 0;
+ },
+ times: rtimes,
+ rerun: function() {
+ bitwiseAndValue = 4294967296;
+ for (var i = 0; i < 600000; i++) {
+ bitwiseAndValue = bitwiseAndValue & i;
+ }
+ result = bitwiseAndValue;
}
},
+
{ name: 'bitops-bits-in-byte.js',
actual: function() {
return result;
},
expected: function() {
return 358400;
+ },
+ times: rtimes,
+ rerun: function() {
+ result = TimeFunc(bitsinbyte);
}
},
+
{ name: 'bitops-nsieve-bits.js',
actual: function() {
var ret = 0;
@@ -190,40 +393,101 @@ var tests = [
},
expected: function() {
return -1286749539853;
+ },
+ times: rtimes,
+ rerun: function() {
+ result = sieve();
}
},
+
{ name: 'bitops-3bit-bits-in-byte.js',
actual: function() {
return sum;
},
expected: function() {
return 512000;
+ },
+ times: rtimes,
+ rerun: function() {
+ sum = TimeFunc(fast3bitlookup);
}
},
+
{ name: 'access-nbody.js',
actual: function() {
return ret;
},
expected: function() {
return -1.3524862408537381;
+ },
+ times: rtimes,
+ rerun: function() {
+ var ret = 0;
+ for (var n = 3; n <= 24; n *= 2) {
+ (function(){
+ var bodies = new NBodySystem( Array(
+ Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
+ ));
+ var max = n * 100;
+
+ ret += bodies.energy();
+ for (var i=0; i<max; i++){
+ bodies.advance(0.01);
+ }
+ ret += bodies.energy();
+ })();
+ }
}
},
+
{ name: 'access-binary-trees.js',
actual: function() {
return ret;
},
expected: function() {
return -4;
+ },
+ times: rtimes,
+ rerun: function() {
+ ret = 0;
+
+ for (var n = 4; n <= 7; n += 1) {
+ var minDepth = 4;
+ var maxDepth = Math.max(minDepth + 2, n);
+ var stretchDepth = maxDepth + 1;
+
+ var check = bottomUpTree(0,stretchDepth).itemCheck();
+
+ var longLivedTree = bottomUpTree(0,maxDepth);
+ for (var depth=minDepth; depth<=maxDepth; depth+=2){
+ var iterations = 1 << (maxDepth - depth + minDepth);
+
+ check = 0;
+ for (var i=1; i<=iterations; i++){
+ check += bottomUpTree(i,depth).itemCheck();
+ check += bottomUpTree(-i,depth).itemCheck();
+ }
+ }
+
+ ret += longLivedTree.itemCheck();
+ }
}
},
+
{ name: 'access-fannkuch.js',
actual: function() {
return ret;
},
expected: function() {
return 22;
+ },
+ times: rtimes,
+ rerun: function() {
+ n = 8;
+ ret = fannkuch(n);
}
},
+
{ name: 'math-spectral-norm.js',
actual: function() {
var ret = '';
@@ -234,32 +498,43 @@ var tests = [
},
expected: function() {
return "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,";
+ },
+ times: rtimes,
+ rerun: function() {
+ total = 0;
+ for (var i = 6; i <= 48; i *= 2) {
+ total += spectralnorm(i);
+ }
}
},
+
{ name: '3d-raytrace.js',
actual: function() {
return hash(testOutput);
},
expected: function() {
return 230692593;
- }
- },
- { name: 'regexp-dna.js',
- actual: function() {
- return dnaOutputString;
},
- expected: function() {
- return "agggtaaa|tttaccct 0\n[cgt]gggtaaa|tttaccc[acg] 9\na[act]ggtaaa|tttacc[agt]t 27\nag[act]gtaaa|tttac[agt]ct 24\nagg[act]taaa|ttta[agt]cct 30\naggg[acg]aaa|ttt[cgt]ccct 9\nagggt[cgt]aa|tt[acg]accct 12\nagggta[cgt]a|t[acg]taccct 9\nagggtaa[cgt]|[acg]ttaccct 15\n";
+ times: rtimes,
+ rerun: function() {
+ testOutput = arrayToCanvasCommands(raytraceScene());
}
},
+
{ name: 'math-cordic.js',
actual: function() {
return total;
},
expected: function() {
return 10362.570468755888;
+ },
+ times: rtimes,
+ rerun: function() {
+ total = 0;
+ cordic(25000);
}
},
+
{ name: 'controlflow-recursive.js',
actual: function() {
var ret = 0;
@@ -272,16 +547,36 @@ var tests = [
},
expected: function() {
return 57775;
+ },
+ times: rtimes,
+ rerun: function() {
+ result = 0;
+ for (var i = 3; i <= 5; i++) {
+ result += ack(3,i);
+ result += fib(17.0+i);
+ result += tak(3*i+3,2*i+2,i+1);
+ }
}
},
+
{ name: 'date-format-tofte.js',
actual: function() {
return shortFormat + longFormat;
},
expected: function() {
return "2008-05-01Thursday, May 01, 2008 6:31:22 PM";
+ },
+ times: rtimes,
+ rerun: function() {
+ date = new Date("1/1/2007 1:11:11");
+ for (i = 0; i < 500; ++i) {
+ var shortFormat = date.formatDate("Y-m-d");
+ var longFormat = date.formatDate("l, F d, Y g:i:s A");
+ date.setTime(date.getTime() + 84266956);
+ }
}
},
+
{ name: 'string-tagcloud.js',
actual: function() {
// The result string embeds floating-point numbers, which can vary a bit on different platforms,
@@ -291,8 +586,71 @@ var tests = [
},
expected: function() {
return 295906;
+ },
+ times: rtimes,
+ rerun: function() {
+ tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } });
+ tagcloud = makeTagCloud(tagInfo);
}
},
+
+ { name: 'math-partial-sums.js',
+ actual: function() {
+ return total;
+ },
+ expected: function() {
+ return 60.08994194659945;
+ },
+ times: rtimes,
+ rerun: function() {
+ total = 0;
+ for (var i = 1024; i <= 16384; i *= 2) {
+ total += partial(i);
+ }
+ }
+ },
+
+ { name: 'access-nsieve.js',
+ actual: function() {
+ return result;
+ },
+ expected: function() {
+ return 14302;
+ },
+ times: rtimes,
+ rerun: function() {
+ result = sieve();
+ }
+ },
+
+ { name: '3d-cube.js',
+ times: rtimes,
+ rerun: function() {
+ Q = new Array();
+ MTrans = new Array(); // transformation matrix
+ MQube = new Array(); // position information of qube
+ I = new Array(); // entity matrix
+ Origin = new Object();
+ Testing = new Object();
+ for ( var i = 20; i <= 160; i *= 2 ) {
+ Init(i);
+ }
+ }
+ },
+
+ //TODO no easy way to sanity check result
+ { name: 'string-fasta.js',
+ times: rtimes,
+ rerun: function() {
+ ret = 0;
+ count = 7;
+ fastaRepeat(2*count*100000, ALU);
+ fastaRandom(3*count*1000, IUB);
+ fastaRandom(5*count*1000, HomoSap);
+ }
+ },
+
+ //TODO no easy way to sanity check result
{ name: 'string-unpack-code.js',
actual: function() {
return decompressedMochiKit.length == 106415 &&
@@ -301,43 +659,32 @@ var tests = [
decompressedMochiKit[82556] == '>';
},
expected: function() {
- return true;
- }
+ return true;
+ },
},
- //TODO no easy way to sanity check result
- { name: 'string-fasta.js' },
- //TODO no easy way to sanity check result
- { name: 'math-partial-sums.js' },
- //TODO no easy way to sanity check result
- { name: 'access-nsieve.js' },
- //TODO no easy way to sanity check result
- { name: '3d-cube.js' },
-];
-
-// handle the case this script may be run by a JS engine that doesn't
-// support __DIR__ global variable.
-var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
-
-var verbose_run = false;
-var args = [];
-if (typeof $ARGS !== 'undefined') {
- args = $ARGS;
-} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
- args = arguments;
-}
+];
-for (i in args) {
- if (args[i] === '--verbose') {
- verbose_run = true;
+tests.sort(function(a,b) { return a.name.localeCompare(b.name); });
+if (typeof single !== 'undefined') {
+ for (i in tests) {
+ if (tests[i].name === single) {
+ singleTest = tests[i];
+ tests = [singleTest];
break;
}
+ }
+ if (tests.length != 1) {
+ throw "unknown single test '" + single + "'";
+ }
}
+
+// handle the case this script may be run by a JS engine that doesn't
+// support __DIR__ global variable.
+
runsuite(tests);
-if (verbose_run) {
- print('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms ");
-}
+pprint('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms ");
print("Sunspider finished!");
diff --git a/test/script/basic/runsunspider-lazy.js.EXPECTED b/test/script/basic/runsunspider.js.EXPECTED
index dd360839..dd360839 100644
--- a/test/script/basic/runsunspider-lazy.js.EXPECTED
+++ b/test/script/basic/runsunspider.js.EXPECTED
diff --git a/test/script/basic/samfunc.js b/test/script/basic/samfunc.js
index 7751bee0..8cd6aed9 100644
--- a/test/script/basic/samfunc.js
+++ b/test/script/basic/samfunc.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -34,7 +34,7 @@
var t1 = new java.lang.Thread(function() {
print("thread t1.run");
-});
+});
// make sure that we can pass interface implementation as well.
var t2 = new java.lang.Thread(new java.lang.Runnable() {
diff --git a/test/script/basic/scripting.js b/test/script/basic/scripting.js
index 88096366..056afc7d 100644
--- a/test/script/basic/scripting.js
+++ b/test/script/basic/scripting.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/scripting.js.EXPECTED b/test/script/basic/scripting.js.EXPECTED
index 4f06475e..3b1b3b6b 100644
--- a/test/script/basic/scripting.js.EXPECTED
+++ b/test/script/basic/scripting.js.EXPECTED
@@ -22,21 +22,21 @@ No we don't
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/sealfreeze.js b/test/script/basic/sealfreeze.js
index 8b932f8f..742ac8c6 100644
--- a/test/script/basic/sealfreeze.js
+++ b/test/script/basic/sealfreeze.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/setlength.js b/test/script/basic/setlength.js
index 45f54e57..6a791928 100644
--- a/test/script/basic/setlength.js
+++ b/test/script/basic/setlength.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
* @test
* @run
*/
-
+
var a = ["a", "b", "c", "d", "e"];
print(a.length);
print(a);
diff --git a/test/script/basic/splitter.js b/test/script/basic/splitter.js
index 62f5ddf9..395e7505 100644
--- a/test/script/basic/splitter.js
+++ b/test/script/basic/splitter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,5 @@
* @fork
*/
-load(__DIR__ + 'prototype.js');
-load(__DIR__ + 'yui.js');
load(__DIR__ + 'NASHORN-689.js');
load(__DIR__ + 'NASHORN-58.js');
diff --git a/test/script/basic/splitter.js.EXPECTED b/test/script/basic/splitter.js.EXPECTED
index dafab972..51ea8615 100644
--- a/test/script/basic/splitter.js.EXPECTED
+++ b/test/script/basic/splitter.js.EXPECTED
@@ -1,6 +1,3 @@
-parsed and compiled ok prototype.js
-parsed and compiled ok yui-min.js
-parsed and compiled ok yui.js
a=10
a=9
a=8
diff --git a/test/script/basic/runsunspider-lazy.js b/test/script/basic/splitter_prototype.js
index 6e24c0c5..ae97616f 100644
--- a/test/script/basic/runsunspider-lazy.js
+++ b/test/script/basic/splitter_prototype.js
@@ -1,34 +1,33 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test various scripts with low splitter threshold
*
* @test
- * @option -timezone=PST
- * @option --lazy-compilation
- * @runif external.sunspider
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.prototype
+ * @fork
*/
-load(__DIR__ + "runsunspider.js");
-
+load(__DIR__ + 'prototype.js');
diff --git a/test/script/basic/splitter_prototype.js.EXPECTED b/test/script/basic/splitter_prototype.js.EXPECTED
new file mode 100644
index 00000000..e677550c
--- /dev/null
+++ b/test/script/basic/splitter_prototype.js.EXPECTED
@@ -0,0 +1 @@
+parsed and compiled ok prototype.js
diff --git a/test/script/basic/splitter_yui.js b/test/script/basic/splitter_yui.js
new file mode 100644
index 00000000..e03f53b9
--- /dev/null
+++ b/test/script/basic/splitter_yui.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test various scripts with low splitter threshold
+ *
+ * @test
+ * @option -Dnashorn.compiler.splitter.threshold=200
+ * @runif external.yui
+ * @fork
+ */
+
+load(__DIR__ + 'yui.js');
diff --git a/test/script/basic/splitter_yui.js.EXPECTED b/test/script/basic/splitter_yui.js.EXPECTED
new file mode 100644
index 00000000..28dd1b9d
--- /dev/null
+++ b/test/script/basic/splitter_yui.js.EXPECTED
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/test/script/basic/stdin.js b/test/script/basic/stdin.js
index a3a93324..1e507e43 100644
--- a/test/script/basic/stdin.js
+++ b/test/script/basic/stdin.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/strings.js b/test/script/basic/strings.js
index 87aff316..62b9dba4 100644
--- a/test/script/basic/strings.js
+++ b/test/script/basic/strings.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/throws.js b/test/script/basic/throws.js
index 30647e47..4e673a4b 100644
--- a/test/script/basic/throws.js
+++ b/test/script/basic/throws.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/tosource.js b/test/script/basic/tosource.js
index ad6cfcc7..43e7ab7f 100644
--- a/test/script/basic/tosource.js
+++ b/test/script/basic/tosource.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/tostring.js b/test/script/basic/tostring.js
index 80e6b0fc..56f5294e 100644
--- a/test/script/basic/tostring.js
+++ b/test/script/basic/tostring.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/try.js b/test/script/basic/try.js
index 07ec43ce..d3d68180 100644
--- a/test/script/basic/try.js
+++ b/test/script/basic/try.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,12 +25,12 @@
* Try throw test.
*
* @test
- * @run
+ * @run
*/
function A() {
print("before try");
-
+
try {
print("before throw");
throw "a string";
@@ -41,7 +41,7 @@ function A() {
} finally {
print("finally");
}
-
+
return "incorrect";
}
diff --git a/test/script/basic/try2.js b/test/script/basic/try2.js
index 8a59c89b..9e50718c 100644
--- a/test/script/basic/try2.js
+++ b/test/script/basic/try2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,21 +25,21 @@
* Try throw test - nest finally
*
* @test
- * @run
+ * @run
*/
function f() {
print("a");
try {
- print("b");
+ print("b");
} finally {
- print("c");
- try {
- print("d");
- } finally {
- print("e");
- }
- print("f");
+ print("c");
+ try {
+ print("d");
+ } finally {
+ print("e");
+ }
+ print("f");
}
print("g");
}
diff --git a/test/script/basic/trybreakcont.js b/test/script/basic/trybreakcont.js
index 94bfdf11..683f26b6 100644
--- a/test/script/basic/trybreakcont.js
+++ b/test/script/basic/trybreakcont.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/trycatch.js b/test/script/basic/trycatch.js
index f5707e47..632c3208 100644
--- a/test/script/basic/trycatch.js
+++ b/test/script/basic/trycatch.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* try catch test.
*
* @test
- * @run
+ * @run
*/
var actual = '';
@@ -35,13 +35,13 @@ test();
function test() {
expect = true;
-
+
try {
actual = true;
}
catch(ex) {
actual = ex + '';
}
-
+
print(actual);
}
diff --git a/test/script/basic/trycatchfor.js b/test/script/basic/trycatchfor.js
index a8c2d09f..953f05d1 100644
--- a/test/script/basic/trycatchfor.js
+++ b/test/script/basic/trycatchfor.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@
try {
for(var i =0; i < 10; i++) {
- }
+ }
} catch (e) {
}
diff --git a/test/script/basic/tryfinallyreturn.js b/test/script/basic/tryfinallyreturn.js
index bc79146f..ed7fe62d 100644
--- a/test/script/basic/tryfinallyreturn.js
+++ b/test/script/basic/tryfinallyreturn.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/tryforbreak.js b/test/script/basic/tryforbreak.js
index 04d8de31..4a625818 100644
--- a/test/script/basic/tryforbreak.js
+++ b/test/script/basic/tryforbreak.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -31,8 +31,8 @@
try {
for(i = 0; i < 3; i++) {
break;
- };
-} catch (e) {
+ };
+} catch (e) {
}
print("done");
diff --git a/test/script/basic/typechange.js b/test/script/basic/typechange.js
index ff416f8d..c930e8a6 100644
--- a/test/script/basic/typechange.js
+++ b/test/script/basic/typechange.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* This test crashes with VerifyError (bad type on stack).
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/typecoerce.js b/test/script/basic/typecoerce.js
index ba95e6ad..3e3bc6df 100644
--- a/test/script/basic/typecoerce.js
+++ b/test/script/basic/typecoerce.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,9 +24,9 @@
/**
* There was a bug in the old Lower that didn't fully propagate type information
* by way of assignment. 'q' in the example below would have finished a double
- * even though it can get an object value through the assignment 'q = l'
- *
- * Furthermore, this caused type coercion to be done at q = l, and not a q = q * 2,
+ * even though it can get an object value through the assignment 'q = l'
+ *
+ * Furthermore, this caused type coercion to be done at q = l, and not a q = q * 2,
* which is a bug. This test ensures it happens in the correct order
*
* @test
@@ -42,11 +42,11 @@ function f() {
var l = 1.2; //number
var q = 2.3; //number
for (var i = 0; i < 2; i++) {
- q = l; // q = toNumber(l), no coercion here
- print("assignment done");
- q = q * 2; // q = q * 2, coercion here
- print("multiplication done");
- l = createObject();
+ q = l; // q = toNumber(l), no coercion here
+ print("assignment done");
+ q = q * 2; // q = q * 2, coercion here
+ print("multiplication done");
+ l = createObject();
}
}
diff --git a/test/script/basic/typedarrays.js b/test/script/basic/typedarrays.js
index 0854bea9..b15f5dd1 100644
--- a/test/script/basic/typedarrays.js
+++ b/test/script/basic/typedarrays.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,20 +25,20 @@
* typedarray test.
*
* @test
- * @run
+ * @run
*/
var typeDefinitions = [
-Int8Array,
-Uint8Array,
-Uint8ClampedArray,
-Int16Array,
-Uint16Array,
-Int32Array,
-Uint32Array,
-Float32Array,
-Float64Array,
+Int8Array,
+Uint8Array,
+Uint8ClampedArray,
+Int16Array,
+Uint16Array,
+Int32Array,
+Uint32Array,
+Float32Array,
+Float64Array,
];
var mem1 = new ArrayBuffer(1024);
@@ -55,17 +55,17 @@ var all = [];
typeDefinitions.forEach(function(arrayDef) {
var p = arrayDef.prototype;
var sub = [];
- sub.push(new arrayDef(mem1, arrayDef.BYTES_PER_ELEMENT, 3));
+ sub.push(new arrayDef(mem1, arrayDef.BYTES_PER_ELEMENT, 3));
sub.push(new arrayDef(size));
sub.push(new arrayDef(arr));
//push the instances, they will be reused to do instance based construction
partial.push({
- instances:sub,
+ instances:sub,
type:arrayDef
});
-
+
all.concat(all, sub);
-
+
});
partial.forEach(function(inst) {
@@ -83,11 +83,11 @@ all.forEach(function(instance) {
var arr = Object.getOwnPropertyNames(instance);
arr.forEach(function(p) {
var val = instance[p];
- if(!isNaN(p)){
+ if(!isNaN(p)) {
val[p] = 99;
- }
+ }
});
-
+
instance.set(instance, 0);
instance.set(instance);
instance.set(arr2);
diff --git a/test/script/basic/typedarrays2.js b/test/script/basic/typedarrays2.js
new file mode 100644
index 00000000..dfbecb0d
--- /dev/null
+++ b/test/script/basic/typedarrays2.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Typed array test 2
+ *
+ * @test
+ * @run
+ */
+
+var b = new ArrayBuffer(8);
+
+var v1 = new Int32Array(b);
+var v2 = new Uint8Array(b, 2);
+var v3 = new Int16Array(b, 2, 2);
+
+v3[1000] = 17;
+v3.apa = 17;
+print(v3[1000]);
+var arr = [1,2,3];
+arr.gegg = 17;
+print(arr.gegg);
+var v4 = new Int32Array(arr);
+print(v4.gegg);
+
+v2[0] = 0xff;
+v2[1] = 0xff;
+if (v2[1] != 0xff) {
+ print("Error 1: " + v2[1]);
+}
+if (v3[0] != -1) {
+ print("Error 2: " + v3[0]);
+}
+
+print("Done");
+
diff --git a/test/script/basic/typedarrays2.js.EXPECTED b/test/script/basic/typedarrays2.js.EXPECTED
new file mode 100644
index 00000000..de377cc5
--- /dev/null
+++ b/test/script/basic/typedarrays2.js.EXPECTED
@@ -0,0 +1,4 @@
+undefined
+17
+undefined
+Done
diff --git a/test/script/basic/typeof.js b/test/script/basic/typeof.js
index 15c9f81c..4e0205f3 100644
--- a/test/script/basic/typeof.js
+++ b/test/script/basic/typeof.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Typeof test.
*
* @test
- * @run
+ * @run
*/
var x = { a: 1, b: "string", c: [1, 2, 3], d: function() {} };
diff --git a/test/script/basic/typeof2.js b/test/script/basic/typeof2.js
index 248fabfb..80513e9f 100644
--- a/test/script/basic/typeof2.js
+++ b/test/script/basic/typeof2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/undefined.js b/test/script/basic/undefined.js
index b949eec5..cd0e885c 100644
--- a/test/script/basic/undefined.js
+++ b/test/script/basic/undefined.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/underscore.js b/test/script/basic/underscore.js
index 064e5252..f9b2a7a8 100644
--- a/test/script/basic/underscore.js
+++ b/test/script/basic/underscore.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* NASHORN-466 : corpus parse test for underscore
- *
+ *
* @test
* @runif external.underscore
*/
diff --git a/test/script/basic/varargs.js b/test/script/basic/varargs.js
index 02844139..061325da 100644
--- a/test/script/basic/varargs.js
+++ b/test/script/basic/varargs.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* Var args test.
*
* @test
- * @run
+ * @run
*/
function varFunc(a, b, c) {
print(a, b, c);
diff --git a/test/script/basic/void.js b/test/script/basic/void.js
index 957f954d..8abc146d 100644
--- a/test/script/basic/void.js
+++ b/test/script/basic/void.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/with.js b/test/script/basic/with.js
index 1ae81130..2e13b281 100644
--- a/test/script/basic/with.js
+++ b/test/script/basic/with.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* With test.
*
* @test
- * @run
+ * @run
*/
var x = {a: 10, b: 20, c: 30};
@@ -38,12 +38,12 @@ print(x.b);
with (x) {
print(b);
print(x.b);
-
+
b = false;
-
+
print(b);
print(x.b);
-
+
y = 200;
}
@@ -52,10 +52,10 @@ print(x.b);
for (i in x) print(i, x[i]);
-var obj = {
+var obj = {
__noSuchProperty__: function(name) {
return name.toUpperCase();
- }
+ }
};
with(obj) {
diff --git a/test/script/basic/withprimitive.js b/test/script/basic/withprimitive.js
index a0ee021f..a3c6db15 100644
--- a/test/script/basic/withprimitive.js
+++ b/test/script/basic/withprimitive.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,7 +24,7 @@
/**
* Using "with" statement with primitive typed value as scope object.
* Results in VerifyError: Bad type on operand stack.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/basic/writable_relink.js b/test/script/basic/writable_relink.js
index ebc8a3bd..378923d4 100644
--- a/test/script/basic/writable_relink.js
+++ b/test/script/basic/writable_relink.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/basic/xorassign.js b/test/script/basic/xorassign.js
index 1cb73b6b..0a6fd377 100644
--- a/test/script/basic/xorassign.js
+++ b/test/script/basic/xorassign.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * The following crashes with VerifyError.
+ * The following crashes with VerifyError.
*
* @test
* @run
diff --git a/test/script/basic/yui.js b/test/script/basic/yui.js
index 879fb57d..9c48af5e 100644
--- a/test/script/basic/yui.js
+++ b/test/script/basic/yui.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,23 +23,23 @@
/**
* NASHORN-469 : corpus parse test for yahoo ui library / yahoo ui library min
- *
+ *
* @test
* @runif external.yui
*/
var names = [ "yui-min.js", "yui.js" ];
-for each (name in names) {
+for each (name in names) {
+ try {
try {
- try {
var file = __DIR__ + "../external/yui/" + name;
- load(__DIR__ + "../external/yui/" + name);
- } catch (e) {
- print(e);
- }
+ load(__DIR__ + "../external/yui/" + name);
+ } catch (e) {
+ print(e);
+ }
} catch (e) {
- print("error: " + e);
+ print("error: " + e);
}
print("parsed and compiled ok " + name);
}
diff --git a/test/script/currently-failing/JDK-8006191.js b/test/script/currently-failing/JDK-8006191.js
index b856c716..ca0dda50 100644
--- a/test/script/currently-failing/JDK-8006191.js
+++ b/test/script/currently-failing/JDK-8006191.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@@ -28,14 +28,14 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
+
/**
* JDK-8006191 - `cmd` -> exec("cmd") in script mode
*
* @test
* @option -scripting
* @argument ArgumentFromCommandLine
- * @run
+ * @run
*/
#!/usr/bin/jjs
diff --git a/test/script/basic/JDK-8010697.js b/test/script/currently-failing/JDK-8010697.js
index c1b8e572..2ed194f0 100644
--- a/test/script/basic/JDK-8010697.js
+++ b/test/script/currently-failing/JDK-8010697.js
@@ -35,7 +35,7 @@ var WeakReferenceArray = Java.type("java.lang.ref.WeakReference[]");
var refArray = new WeakReferenceArray(N);
for (var i = 0; i < N; i ++) {
- var object = new java.lang.Object();
+ var object = new java.awt.Color(0,0,0);//lang.Object();
array[i] = object;
refArray[i] = new java.lang.ref.WeakReference(object);
}
@@ -48,11 +48,11 @@ for (var i = 0; i < N; i ++) {
java.lang.System.gc();
java.lang.System.gc();
+java.lang.System.gc();
for (var i = 0; i < N; i ++) {
if (refArray[i].get() != null) {
- print("Reference found at " + i);
- exit(0);
+ print("Reference found at " + i + " " + refArray + " " + refArray[i].get());
}
}
diff --git a/test/script/basic/JDK-8010697.js.EXPECTED b/test/script/currently-failing/JDK-8010697.js.EXPECTED
index fe741090..fe741090 100644
--- a/test/script/basic/JDK-8010697.js.EXPECTED
+++ b/test/script/currently-failing/JDK-8010697.js.EXPECTED
diff --git a/test/script/currently-failing/apply_to_call_bench.js b/test/script/currently-failing/apply_to_call_bench.js
new file mode 100644
index 00000000..5c10977b
--- /dev/null
+++ b/test/script/currently-failing/apply_to_call_bench.js
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * sanity check that apply to call specialization is faster than apply.
+ *
+ * @test
+ * @run
+ */
+
+var Class = {
+ create: function() {
+ return function() { //vararg
+ this.initialize.apply(this, arguments);
+ }
+ }
+};
+
+Color = Class.create();
+Color.prototype = {
+ red: 0, green: 0, blue: 0,
+ initialize: function(r,g,b) {
+ this.red = r;
+ this.green = g;
+ this.blue = b;
+ }
+};
+
+var time1 = 0;
+var time2 = 0;
+
+function set_time1(t) {
+ time1 = t;
+}
+
+function set_time2(t) {
+ time2 = t;
+}
+
+function bench(x, set_time) {
+ var d = new Date;
+ var colors = new Array(16);
+ for (var i=0;i<1e8;i++) {
+ colors[i & 0xf] = new Color(1,2,3);
+ }
+ var t = new Date - d;
+ set_time(t);
+ return colors;
+}
+
+//warmup
+print("Running warmup");
+bench(17, set_time1);
+
+print("Running sharp run");
+bench(17, set_time1);
+
+print("Swapping out call");
+Function.prototype.call = function() {
+ throw "This should not happen, apply should be called instead";
+};
+
+print("Rerunning invalidated");
+bench(17, set_time2);
+
+print("All done!");
+
+if (time1 > time2) {
+ print("ERROR: time1 > time2 (" + time1 + " > " + time2 + ")");
+} else {
+ print("Times OK");
+}
+
diff --git a/test/script/currently-failing/apply_to_call_bench.js.EXPECTED b/test/script/currently-failing/apply_to_call_bench.js.EXPECTED
new file mode 100644
index 00000000..ad3cbf1e
--- /dev/null
+++ b/test/script/currently-failing/apply_to_call_bench.js.EXPECTED
@@ -0,0 +1,6 @@
+Running warmup
+Running sharp run
+Swapping out call
+Rerunning invalidated
+All done!
+Times OK
diff --git a/test/script/currently-failing/clone_ir.js b/test/script/currently-failing/clone_ir.js
index 3c1eccf2..14009506 100644
--- a/test/script/currently-failing/clone_ir.js
+++ b/test/script/currently-failing/clone_ir.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -41,12 +41,12 @@ var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context$ThrowErr
var System = Java.type("java.lang.System");
var toArrayMethod = ASTWriter.class.getMethod("toArray");
-var parseMethod = Parser.class.getMethod("parse");
+var parseMethod = Parser.class.getMethod("parse");
function toString(obj) {
var output = "{ ";
for (property in obj) {
- output += property + ': ' + obj[property]+'; ';
+ output += property + ': ' + obj[property]+'; ';
}
return output + '}'
}
@@ -54,11 +54,11 @@ function toString(obj) {
function flatten(func) {
var writer = new ASTWriter(func);
var funcList = toArrayMethod.invoke(writer);
-
+
var res = [];
for each (x in funcList) {
- res.push({ name: x.getClass().getName(), id: System.identityHashCode(x) });
- }
+ res.push({ name: x.getClass().getName(), id: System.identityHashCode(x) });
+ }
return res;
}
@@ -80,20 +80,20 @@ function check_src(src) {
print(f2.map(toString));
if (f1.length != f2.length) {
- print("length difference between original and clone " + f1.length + " != " + f2.length);
- return false;
+ print("length difference between original and clone " + f1.length + " != " + f2.length);
+ return false;
}
for (var i = 0; i < f1.length; i++) {
- if (f1[i].name !== f2[i].name) {
- print("name conflict at " + i + " " + f1[i].name + " != " + f2[i].name);
- return false;
- } else if (f1[i].id === f2[i].id) {
- print("id problem at " + i + " " + toString(f1[i]) + " was not deep copied to " + toString(f2[i]) + " became " + f1[i].id + " != " + f2[i].id);
- return false;
- }
+ if (f1[i].name !== f2[i].name) {
+ print("name conflict at " + i + " " + f1[i].name + " != " + f2[i].name);
+ return false;
+ } else if (f1[i].id === f2[i].id) {
+ print("id problem at " + i + " " + toString(f1[i]) + " was not deep copied to " + toString(f2[i]) + " became " + f1[i].id + " != " + f2[i].id);
+ return false;
}
-
+ }
+
return true;
}
diff --git a/test/script/currently-failing/gettersetter.js b/test/script/currently-failing/gettersetter.js
index 88f69492..5fec25d7 100644
--- a/test/script/currently-failing/gettersetter.js
+++ b/test/script/currently-failing/gettersetter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/currently-failing/logcoverage.js b/test/script/currently-failing/logcoverage.js
index 2d8d410a..0c78c1dc 100644
--- a/test/script/currently-failing/logcoverage.js
+++ b/test/script/currently-failing/logcoverage.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* mh_coverage.js
- * Screen scrape various logs to ensure that we cover enough functionality,
+ * Screen scrape various logs to ensure that we cover enough functionality,
* e.g. method handle instrumentation
*
* @test
@@ -44,25 +44,25 @@ function runScriptEngine(opts, name) {
var fac = new NashornScriptEngineFactory();
// get current System.err
var oldErr = System.err;
- var oldOut = System.out;
+ var oldOut = System.out;
var baosErr = new ByteArrayOutputStream();
var newErr = new PrintStream(baosErr);
var baosOut = new ByteArrayOutputStream();
- var newOut = new PrintStream(baosOut);
+ var newOut = new PrintStream(baosOut);
try {
// set new standard err
System.setErr(newErr);
System.setOut(newOut);
var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
- var reader = new java.io.FileReader(name);
+ var reader = new java.io.FileReader(name);
engine.eval(reader);
newErr.flush();
- newOut.flush();
+ newOut.flush();
return new java.lang.String(baosErr.toByteArray());
} finally {
// restore System.err to old value
System.setErr(oldErr);
- System.setOut(oldOut);
+ System.setOut(oldOut);
}
}
}
@@ -70,27 +70,27 @@ function runScriptEngine(opts, name) {
var str;
var methodsCalled = [
- 'asCollector',
- 'asType',
- 'bindTo',
- 'dropArguments',
- 'explicitCastArguments',
- 'filterArguments',
- 'filterReturnValue',
- 'findStatic',
- 'findVirtual',
- 'foldArguments',
- 'getter',
- 'guardWithTest',
- 'insertArguments',
- 'methodType',
+ 'asCollector',
+ 'asType',
+ 'bindTo',
+ 'dropArguments',
+ 'explicitCastArguments',
+ 'filterArguments',
+ 'filterReturnValue',
+ 'findStatic',
+ 'findVirtual',
+ 'foldArguments',
+ 'getter',
+ 'guardWithTest',
+ 'insertArguments',
+ 'methodType',
'setter'
];
function check(str, strs) {
for each (s in strs) {
if (str.indexOf(s) !== -1) {
- continue;
+ continue;
}
print(s + " not found");
return;
diff --git a/test/script/currently-failing/optimistic_check_type_cases.js b/test/script/currently-failing/optimistic_check_type_cases.js
new file mode 100644
index 00000000..80dc7590
--- /dev/null
+++ b/test/script/currently-failing/optimistic_check_type_cases.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8035652,8037858
+ * @summary Implement tests that checks static types in the compiled code
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = b = c = 3;
+
+//JDK-8035652
+print(inspect(a/a, "global int division by global int"))
+print(inspect(a%a, "global int modulus by global int"))
+print(inspect(b+=b, "global int addition assignment global int"))
+//JDK-8037858
+print(inspect(b-=b, "global int substraction assignment global int"))
+print(inspect(c*=a, "global int multiplication assignment global int"))
+print(inspect(a/=a, "global int division assignment global int"))
+print(inspect(c%=c, "global int modulo assignment global int"))
diff --git a/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED b/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED
new file mode 100644
index 00000000..eb0573be
--- /dev/null
+++ b/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED
@@ -0,0 +1,7 @@
+global int division by global int: int
+global int modulus by global int: int
+global int addition assignment global int: int
+global int substraction assignment global int: int
+global int multiplication assignment global int: int
+global int division assignment global int: int
+global int modulo assignment global int: int \ No newline at end of file
diff --git a/test/script/maptests/property_delete.js b/test/script/currently-failing/property_delete.js
index e2824dd6..ab508bf2 100644
--- a/test/script/maptests/property_delete.js
+++ b/test/script/currently-failing/property_delete.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8008814-1.js b/test/script/error/JDK-8008814-1.js
index 324d090c..7cfa7a3c 100644
--- a/test/script/error/JDK-8008814-1.js
+++ b/test/script/error/JDK-8008814-1.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8008814-2.js b/test/script/error/JDK-8008814-2.js
index 079b253f..fcc0cce1 100644
--- a/test/script/error/JDK-8008814-2.js
+++ b/test/script/error/JDK-8008814-2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8016522.js b/test/script/error/JDK-8016522.js
index e0832280..58e9b2f4 100644
--- a/test/script/error/JDK-8016522.js
+++ b/test/script/error/JDK-8016522.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8020437-2.js b/test/script/error/JDK-8020437-2.js
index dcd1e173..7dbc2aac 100644
--- a/test/script/error/JDK-8020437-2.js
+++ b/test/script/error/JDK-8020437-2.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8020437.js b/test/script/error/JDK-8020437.js
index e8b84c98..6d03aa48 100644
--- a/test/script/error/JDK-8020437.js
+++ b/test/script/error/JDK-8020437.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8026039.js b/test/script/error/JDK-8026039.js
index f37d9bdd..65fd3d75 100644
--- a/test/script/error/JDK-8026039.js
+++ b/test/script/error/JDK-8026039.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,4 +29,4 @@
function public() {"use strict"}
-function f(public) {"use strict"}
+function f(public) {"use strict"}
diff --git a/test/script/error/JDK-8026039.js.EXPECTED b/test/script/error/JDK-8026039.js.EXPECTED
index cde398f3..4166339c 100644
--- a/test/script/error/JDK-8026039.js.EXPECTED
+++ b/test/script/error/JDK-8026039.js.EXPECTED
@@ -2,7 +2,7 @@ test/script/error/JDK-8026039.js:30:9 "public" cannot be used as function name i
function public() {"use strict"}
^
test/script/error/JDK-8026039.js:32:11 Expected ident but found public
-function f(public) {"use strict"}
+function f(public) {"use strict"}
^
test/script/error/JDK-8026039.js:33:0 Expected } but found eof
diff --git a/test/script/error/JDK-8027933.js b/test/script/error/JDK-8027933.js
index 9b398fa5..2c1dc1f3 100644
--- a/test/script/error/JDK-8027933.js
+++ b/test/script/error/JDK-8027933.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/JDK-8039047.js b/test/script/error/JDK-8039047.js
index 8cbd51fd..042dcb25 100644
--- a/test/script/error/JDK-8039047.js
+++ b/test/script/error/JDK-8039047.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-154/function_mult_params_in_strict.js b/test/script/error/NASHORN-154/function_mult_params_in_strict.js
index 12b1669a..ac5ae9e5 100644
--- a/test/script/error/NASHORN-154/function_mult_params_in_strict.js
+++ b/test/script/error/NASHORN-154/function_mult_params_in_strict.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,8 +24,8 @@
/**
* Early error reporting.
*
- * The occurrence of an Identifier value appearing more than once within a
- * FormalParameterList of an individual strict mode FunctionDeclaration or
+ * The occurrence of an Identifier value appearing more than once within a
+ * FormalParameterList of an individual strict mode FunctionDeclaration or
* FunctionExpression
*
* @test/compile-error
diff --git a/test/script/error/NASHORN-154/improper_return_break_continue.js b/test/script/error/NASHORN-154/improper_return_break_continue.js
index 7496d77f..3fc374e9 100644
--- a/test/script/error/NASHORN-154/improper_return_break_continue.js
+++ b/test/script/error/NASHORN-154/improper_return_break_continue.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-154/invalid_lvalue.js b/test/script/error/NASHORN-154/invalid_lvalue.js
index ce284625..1625cce3 100644
--- a/test/script/error/NASHORN-154/invalid_lvalue.js
+++ b/test/script/error/NASHORN-154/invalid_lvalue.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,8 +24,8 @@
/**
* Early error reporting.
*
- * Attempts to call PutValue on any value for which an early determination can
- * be made that the value is not a Reference (for example, executing the
+ * Attempts to call PutValue on any value for which an early determination can
+ * be made that the value is not a Reference (for example, executing the
* assignment statement 3=4).
*
* @test/compile-error
diff --git a/test/script/error/NASHORN-154/literal_data_and_accessor.js b/test/script/error/NASHORN-154/literal_data_and_accessor.js
index 4a236f12..c46e2369 100644
--- a/test/script/error/NASHORN-154/literal_data_and_accessor.js
+++ b/test/script/error/NASHORN-154/literal_data_and_accessor.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-154/literal_mult_getters.js b/test/script/error/NASHORN-154/literal_mult_getters.js
index 8777b61d..b168417a 100644
--- a/test/script/error/NASHORN-154/literal_mult_getters.js
+++ b/test/script/error/NASHORN-154/literal_mult_getters.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,8 +24,8 @@
/**
* Early error reporting.
*
- * Attempts to define an ObjectLiteral that has multiple get property
- * assignments with the same name or multiple set property assignments with
+ * Attempts to define an ObjectLiteral that has multiple get property
+ * assignments with the same name or multiple set property assignments with
* the same name.
*
* @test/compile-error
diff --git a/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js b/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
index 30d3fad4..b6876a99 100644
--- a/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
+++ b/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -24,7 +24,7 @@
/**
* Early error reporting.
*
- * Attempts in strict mode code to define an ObjectLiteral that has multiple
+ * Attempts in strict mode code to define an ObjectLiteral that has multiple
* data property assignments with the same name.
*
* @test/compile-error
diff --git a/test/script/error/NASHORN-154/with_in_strict.js b/test/script/error/NASHORN-154/with_in_strict.js
index 866c8223..e9b0bba2 100644
--- a/test/script/error/NASHORN-154/with_in_strict.js
+++ b/test/script/error/NASHORN-154/with_in_strict.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-214.js b/test/script/error/NASHORN-214.js
index afffec20..43496196 100644
--- a/test/script/error/NASHORN-214.js
+++ b/test/script/error/NASHORN-214.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-35.js b/test/script/error/NASHORN-35.js
index 314cd3a7..3ba60805 100644
--- a/test/script/error/NASHORN-35.js
+++ b/test/script/error/NASHORN-35.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-39.js b/test/script/error/NASHORN-39.js
index 59f4a4a1..7afef41b 100644
--- a/test/script/error/NASHORN-39.js
+++ b/test/script/error/NASHORN-39.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -29,5 +29,5 @@
// line terminator here should result in compiler error.
-throw
+throw
1;
diff --git a/test/script/error/NASHORN-568.js b/test/script/error/NASHORN-568.js
index 1a8159e8..0701a1aa 100644
--- a/test/script/error/NASHORN-568.js
+++ b/test/script/error/NASHORN-568.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-57.js b/test/script/error/NASHORN-57.js
index 2dc5b15a..fd5ce73a 100644
--- a/test/script/error/NASHORN-57.js
+++ b/test/script/error/NASHORN-57.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/NASHORN-668.js b/test/script/error/NASHORN-668.js
index f3328562..8abf6ca5 100644
--- a/test/script/error/NASHORN-668.js
+++ b/test/script/error/NASHORN-668.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/quotemissing.js b/test/script/error/quotemissing.js
index 74d9a3e9..3a70122f 100644
--- a/test/script/error/quotemissing.js
+++ b/test/script/error/quotemissing.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/error/strictmode.js b/test/script/error/strictmode.js
index abdf2166..05a8e5f8 100644
--- a/test/script/error/strictmode.js
+++ b/test/script/error/strictmode.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/jfx/kaleidoscope.js b/test/script/jfx/kaleidoscope.js
index 4430ff01..438ceacf 100644
--- a/test/script/jfx/kaleidoscope.js
+++ b/test/script/jfx/kaleidoscope.js
@@ -52,99 +52,99 @@ var prv_x,prv_y,prv_x2,prv_y2;
var isFrameRendered = false;
function renderFrame() {
- if (!isFrameRendered) {
+ if (!isFrameRendered) {
a=0.2*angle;
- b=0.7*angle;
- r=0;
- fade=32;
- for(var i=0;i<6;i++)
- {
- c[i]=1.0/(i+1)/2;
- d[i]=1.0/(i+1)/2;
- }
- radius=Math.round((WIDTH+HEIGHT)/8);
- e=radius*0.2;
- p_x=Math.round(WIDTH/2);
- p_y=Math.round(HEIGHT/2);
- x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
- y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
+ b=0.7*angle;
+ r=0;
+ fade=32;
+ for(var i=0;i<6;i++)
+ {
+ c[i]=1.0/(i+1)/2;
+ d[i]=1.0/(i+1)/2;
+ }
+ radius=Math.round((WIDTH+HEIGHT)/8);
+ e=radius*0.2;
+ p_x=Math.round(WIDTH/2);
+ p_y=Math.round(HEIGHT/2);
+ x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
+ y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
isFrameRendered = true;
}
anim();
}
function anim() {
- var a1=Math.cos(a*2);
- var a2=Math.cos(a*4);
- var a3=Math.cos(a);
- var a4=Math.sin(a);
- if(b>limit1&&b<limit2) {
- r+=radius*0.02*a1;
- prv_x=x;
- prv_y=y;
- x=prv_x2+r*a3;
- y=prv_y2+r*a4;
- } else {
- prv_x=x;
- prv_y=y;
- prv_x2=x;
- prv_y2=y;
- x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
- y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
- }
- var c3=16*Math.cos(a*10);
- var c1=Math.floor(56*Math.cos(a*angle*4)+c3);
- var c2=Math.floor(56*Math.sin(a*angle*4)-c3);
- context.lineCap=StrokeLineCap.ROUND;
- context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.01-0.005*-a1)+')'));
- context.lineWidth=e*1.4+e*0.8*a3;
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- context.lineWidth=e+e*0.8*a3;
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.06-0.03*-a1)+')'));
- context.lineWidth=e*0.6+e*0.35*a3;
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- context.setStroke(Paint.valueOf('rgba(0,0,0,0.06)'));
- context.lineWidth=e*0.4+e*0.225*a3;
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.1-0.075*-a1)+')'));
- context.lineWidth=e*0.2+e*0.1*a3;
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- context.setStroke(Paint.valueOf('rgba(255,255,255,0.4)'));
- context.lineWidth=e*(0.1-0.05*-a2);
- draw_line(p_x,p_y,prv_x,prv_y,x,y);
- a+=angle*Math.cos(b);
- b+=angle*0.1;
+ var a1=Math.cos(a*2);
+ var a2=Math.cos(a*4);
+ var a3=Math.cos(a);
+ var a4=Math.sin(a);
+ if(b>limit1&&b<limit2) {
+ r+=radius*0.02*a1;
+ prv_x=x;
+ prv_y=y;
+ x=prv_x2+r*a3;
+ y=prv_y2+r*a4;
+ } else {
+ prv_x=x;
+ prv_y=y;
+ prv_x2=x;
+ prv_y2=y;
+ x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
+ y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
+ }
+ var c3=16*Math.cos(a*10);
+ var c1=Math.floor(56*Math.cos(a*angle*4)+c3);
+ var c2=Math.floor(56*Math.sin(a*angle*4)-c3);
+ context.lineCap=StrokeLineCap.ROUND;
+ context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.01-0.005*-a1)+')'));
+ context.lineWidth=e*1.4+e*0.8*a3;
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ context.lineWidth=e+e*0.8*a3;
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.06-0.03*-a1)+')'));
+ context.lineWidth=e*0.6+e*0.35*a3;
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ context.setStroke(Paint.valueOf('rgba(0,0,0,0.06)'));
+ context.lineWidth=e*0.4+e*0.225*a3;
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.1-0.075*-a1)+')'));
+ context.lineWidth=e*0.2+e*0.1*a3;
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ context.setStroke(Paint.valueOf('rgba(255,255,255,0.4)'));
+ context.lineWidth=e*(0.1-0.05*-a2);
+ draw_line(p_x,p_y,prv_x,prv_y,x,y);
+ a+=angle*Math.cos(b);
+ b+=angle*0.1;
}
function draw_line(x,y,x1,y1,x2,y2) {
- context.beginPath();
- context.moveTo(x+x1,y+y1);
- context.lineTo(x+x2,y+y2);
- context.moveTo(x-x1,y+y1);
- context.lineTo(x-x2,y+y2);
- context.moveTo(x-x1,y-y1);
- context.lineTo(x-x2,y-y2);
- context.moveTo(x+x1,y-y1);
- context.lineTo(x+x2,y-y2);
- context.moveTo(x+y1,y+x1);
- context.lineTo(x+y2,y+x2);
- context.moveTo(x-y1,y+x1);
- context.lineTo(x-y2,y+x2);
- context.moveTo(x-y1,y-x1);
- context.lineTo(x-y2,y-x2);
- context.moveTo(x+y1,y-x1);
- context.lineTo(x+y2,y-x2);
- context.moveTo(x,y+x2);
- context.lineTo(x,y+x1);
- context.moveTo(x,y-x2);
- context.lineTo(x,y-x1);
- context.moveTo(x+x2,y);
- context.lineTo(x+x1,y);
- context.moveTo(x-x2,y);
- context.lineTo(x-x1,y);
- context.stroke();
- context.closePath();
+ context.beginPath();
+ context.moveTo(x+x1,y+y1);
+ context.lineTo(x+x2,y+y2);
+ context.moveTo(x-x1,y+y1);
+ context.lineTo(x-x2,y+y2);
+ context.moveTo(x-x1,y-y1);
+ context.lineTo(x-x2,y-y2);
+ context.moveTo(x+x1,y-y1);
+ context.lineTo(x+x2,y-y2);
+ context.moveTo(x+y1,y+x1);
+ context.lineTo(x+y2,y+x2);
+ context.moveTo(x-y1,y+x1);
+ context.lineTo(x-y2,y+x2);
+ context.moveTo(x-y1,y-x1);
+ context.lineTo(x-y2,y-x2);
+ context.moveTo(x+y1,y-x1);
+ context.lineTo(x+y2,y-x2);
+ context.moveTo(x,y+x2);
+ context.lineTo(x,y+x1);
+ context.moveTo(x,y-x2);
+ context.lineTo(x,y-x1);
+ context.moveTo(x+x2,y);
+ context.lineTo(x+x1,y);
+ context.moveTo(x-x2,y);
+ context.lineTo(x-x1,y);
+ context.stroke();
+ context.closePath();
}
var stack = new StackPane();
diff --git a/test/script/jfx/spread.js b/test/script/jfx/spread.js
index 4a8f38ce..8312d1f9 100644
--- a/test/script/jfx/spread.js
+++ b/test/script/jfx/spread.js
@@ -211,7 +211,7 @@ $STAGE.scene = new Scene(stack);
var timer = new AnimationTimerExtend() {
handle: function handle(now) {
if (frame < 200) {
- draw_frame();
+ draw_frame();
} else {
checkImageAndExit();
timer.stop();
diff --git a/test/script/maptests/builtins.js b/test/script/maptests/builtins.js
index 4de2ec9a..8bfd8489 100644
--- a/test/script/maptests/builtins.js
+++ b/test/script/maptests/builtins.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/maptests/constructor.js b/test/script/maptests/constructor.js
index 5722a3c1..f409ce1b 100644
--- a/test/script/maptests/constructor.js
+++ b/test/script/maptests/constructor.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,4 +33,4 @@ load(__DIR__ + "point.js");
// These objects should share the map
assertSameMap(new Point(2, 3), new Point(43, 23));
assertSameMap(new Point(), new Point());
-assertSameMap(new Point(), new Point(3, 1));
+assertEqualWithoutTypeMap(new Point(), new Point(3, 1));
diff --git a/test/script/maptests/maputil.js b/test/script/maptests/maputil.js
index aa85d7f1..2294e750 100644
--- a/test/script/maptests/maputil.js
+++ b/test/script/maptests/maputil.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -27,7 +27,7 @@
function assertSameMap(obj1, obj2, msg) {
if (! Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
- fail(obj1.constructor + " instances don't share map");
+ fail(obj1.constructor + " instances don't share map " + Debug.diffPropertyMaps(Debug.map(obj1), Debug.map(obj2)));
}
}
@@ -36,3 +36,9 @@ function assertNotSameMap(obj1, obj2, msg) {
fail(obj1.constructor + " and " + obj2.constructor + " instances share map");
}
}
+
+function assertEqualWithoutTypeMap(obj1, obj2, msg) {
+ if (!Debug.equalWithoutType(Debug.map(obj1), Debug.map(obj2))) {
+ fail(obj1.constructor + " and " + obj2.constructor + " instances don't have identical (without considering property types) maps");
+ }
+}
diff --git a/test/script/maptests/object_create.js b/test/script/maptests/object_create.js
index 1b1bd604..e0b5f607 100644
--- a/test/script/maptests/object_create.js
+++ b/test/script/maptests/object_create.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/maptests/object_literals.js b/test/script/maptests/object_literals.js
index c73d8014..b379ac64 100644
--- a/test/script/maptests/object_literals.js
+++ b/test/script/maptests/object_literals.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -42,5 +42,5 @@ assertSameMap(makeObject2(), makeObject2());
// Object literals created at different callsites
assertSameMap({}, {});
-assertSameMap({foo: 4}, {foo: 'hello'});
-assertSameMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
+assertEqualWithoutTypeMap({foo: 4}, {foo: 'hello'});
+assertEqualWithoutTypeMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
diff --git a/test/script/maptests/point.js b/test/script/maptests/point.js
index 38b8fa25..06b64dd6 100644
--- a/test/script/maptests/point.js
+++ b/test/script/maptests/point.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -46,4 +46,4 @@ load(__DIR__ + "maputil.js");
assertSameMap(new Point(2, 3), new Point(43, 23));
assertSameMap(new Point(), new Point());
-assertSameMap(new Point(), new Point(3, 1));
+assertEqualWithoutTypeMap(new Point(), new Point(3, 1));
diff --git a/test/script/maptests/property_add.js b/test/script/maptests/property_add.js
index 20264554..606f2d09 100644
--- a/test/script/maptests/property_add.js
+++ b/test/script/maptests/property_add.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -43,4 +43,4 @@ function addX(obj, val) {
addX(obj1, 3);
addX(obj2, 'hello');
-assertSameMap(obj1, obj2);
+assertEqualWithoutTypeMap(obj1, obj2);
diff --git a/test/script/maptests/proto.js b/test/script/maptests/proto.js
index afb59509..5bc3332c 100644
--- a/test/script/maptests/proto.js
+++ b/test/script/maptests/proto.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/markdown.js b/test/script/markdown.js
new file mode 100644
index 00000000..f1c46256
--- /dev/null
+++ b/test/script/markdown.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Base library for Showdown markdown engine Nashorn testing.
+ * @subtest
+ *
+ *
+ */
+
+load(__DIR__ + "external/showdown/showdown.js");
+var shdwn = Showdown;
+var window = {
+ Showdown: shdwn
+}
+load(__DIR__ + "external/showdown/table.js");
+var converter = new Showdown.converter({extensions: ['table']});
+
diff --git a/test/script/markdown/anchors-by-reference.js b/test/script/markdown/anchors-by-reference.js
new file mode 100644
index 00000000..20a87619
--- /dev/null
+++ b/test/script/markdown/anchors-by-reference.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThis is [an example][id] reference-style link.\nThis is [another] [foo] reference-style link.\nThis is [a third][bar] reference-style link.\nThis is [a fourth][4] reference-style link.\n\n [id]: http://example.com/ \"Optional Title Here\"\n [foo]: http://example.com/ (Optional Title Here)\n [bar]: http://example.com/ (Optional Title Here)\n [4]: <http://example.com/>\n \"Optional Title Here\"";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/anchors-by-reference.js.EXPECTED b/test/script/markdown/anchors-by-reference.js.EXPECTED
new file mode 100644
index 00000000..6115d50e
--- /dev/null
+++ b/test/script/markdown/anchors-by-reference.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">another</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">a third</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>
diff --git a/test/script/markdown/automatic-anchors.js b/test/script/markdown/automatic-anchors.js
new file mode 100644
index 00000000..260dd59f
--- /dev/null
+++ b/test/script/markdown/automatic-anchors.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n<http://example.com/>";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/automatic-anchors.js.EXPECTED b/test/script/markdown/automatic-anchors.js.EXPECTED
new file mode 100644
index 00000000..6de71a9d
--- /dev/null
+++ b/test/script/markdown/automatic-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p><a href="http://example.com/">http://example.com/</a></p>
diff --git a/test/script/markdown/blockquote-nested-markdown.js b/test/script/markdown/blockquote-nested-markdown.js
new file mode 100644
index 00000000..c0309601
--- /dev/null
+++ b/test/script/markdown/blockquote-nested-markdown.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "> ## This is a header.\n>\n> 1. This is the first list item.\n> 2. This is the second list item.\n>\n> Here's some example code:\n>\n> return shell_exec(\"echo $input | $markdown_script\");";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/blockquote-nested-markdown.js.EXPECTED b/test/script/markdown/blockquote-nested-markdown.js.EXPECTED
new file mode 100644
index 00000000..b32199ce
--- /dev/null
+++ b/test/script/markdown/blockquote-nested-markdown.js.EXPECTED
@@ -0,0 +1,13 @@
+<blockquote>
+ <h2 id="thisisaheader">This is a header.</h2>
+
+ <ol>
+ <li>This is the first list item.</li>
+ <li>This is the second list item.</li>
+ </ol>
+
+ <p>Here's some example code:</p>
+
+<pre><code>return shell_exec("echo $input | $markdown_script");
+</code></pre>
+</blockquote>
diff --git a/test/script/markdown/blockquote.js b/test/script/markdown/blockquote.js
new file mode 100644
index 00000000..e342b016
--- /dev/null
+++ b/test/script/markdown/blockquote.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = " \n > This is a multi line blockquote test\n >\n > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/blockquote.js.EXPECTED b/test/script/markdown/blockquote.js.EXPECTED
new file mode 100644
index 00000000..c4956bbe
--- /dev/null
+++ b/test/script/markdown/blockquote.js.EXPECTED
@@ -0,0 +1,5 @@
+<blockquote>
+ <p>This is a multi line blockquote test</p>
+
+ <p>With more than one line.</p>
+</blockquote>
diff --git a/test/script/markdown/code-block-html-escape.js b/test/script/markdown/code-block-html-escape.js
new file mode 100644
index 00000000..9ea178d8
--- /dev/null
+++ b/test/script/markdown/code-block-html-escape.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThis is some HTML:\n\n <h1>Heading</h1>";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/code-block-html-escape.js.EXPECTED b/test/script/markdown/code-block-html-escape.js.EXPECTED
new file mode 100644
index 00000000..028f874d
--- /dev/null
+++ b/test/script/markdown/code-block-html-escape.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is some HTML:</p>
+
+<pre><code>&lt;h1&gt;Heading&lt;/h1&gt;
+</code></pre>
diff --git a/test/script/markdown/code-block.js b/test/script/markdown/code-block.js
new file mode 100644
index 00000000..e3f74298
--- /dev/null
+++ b/test/script/markdown/code-block.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThis is a normal paragraph:\n\n This is a code block.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/code-block.js.EXPECTED b/test/script/markdown/code-block.js.EXPECTED
new file mode 100644
index 00000000..3e560997
--- /dev/null
+++ b/test/script/markdown/code-block.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is a normal paragraph:</p>
+
+<pre><code>This is a code block.
+</code></pre>
diff --git a/test/script/markdown/doubline-list.js b/test/script/markdown/doubline-list.js
new file mode 100644
index 00000000..bb56ea5e
--- /dev/null
+++ b/test/script/markdown/doubline-list.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n * Bird\n\n * Magic";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/doubline-list.js.EXPECTED b/test/script/markdown/doubline-list.js.EXPECTED
new file mode 100644
index 00000000..1065a445
--- /dev/null
+++ b/test/script/markdown/doubline-list.js.EXPECTED
@@ -0,0 +1,4 @@
+<ul>
+<li><p>Bird</p></li>
+<li><p>Magic</p></li>
+</ul>
diff --git a/test/script/markdown/emphasis.js b/test/script/markdown/emphasis.js
new file mode 100644
index 00000000..17752079
--- /dev/null
+++ b/test/script/markdown/emphasis.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n*important*\n\n_important_\n\nthis mid*important*sentence";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/emphasis.js.EXPECTED b/test/script/markdown/emphasis.js.EXPECTED
new file mode 100644
index 00000000..a1fda4ab
--- /dev/null
+++ b/test/script/markdown/emphasis.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><em>important</em></p>
+
+<p><em>important</em></p>
+
+<p>this mid<em>important</em>sentence</p>
diff --git a/test/script/markdown/escaped-number-period.js b/test/script/markdown/escaped-number-period.js
new file mode 100644
index 00000000..b21776cd
--- /dev/null
+++ b/test/script/markdown/escaped-number-period.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "It happened in 1986\. What a great season.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/escaped-number-period.js.EXPECTED b/test/script/markdown/escaped-number-period.js.EXPECTED
new file mode 100644
index 00000000..0ea83bac
--- /dev/null
+++ b/test/script/markdown/escaped-number-period.js.EXPECTED
@@ -0,0 +1 @@
+<p>It happened in 1986. What a great season.</p>
diff --git a/test/script/markdown/escaping.js b/test/script/markdown/escaping.js
new file mode 100644
index 00000000..c9897f79
--- /dev/null
+++ b/test/script/markdown/escaping.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThese should all be escaped:\n\n\\\n\n\`\n\n\*\n\n\_\n\n\{\n\n\}\n\n\[\n\n\]\n\n\(\n\n\)\n\n\#\n\n\+\n\n\-\n\n\.\n\n\!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/escaping.js.EXPECTED b/test/script/markdown/escaping.js.EXPECTED
new file mode 100644
index 00000000..1ac6a291
--- /dev/null
+++ b/test/script/markdown/escaping.js.EXPECTED
@@ -0,0 +1,31 @@
+<p>These should all be escaped:</p>
+
+<p>\</p>
+
+<p>`</p>
+
+<p>*</p>
+
+<p>_</p>
+
+<p>{</p>
+
+<p>}</p>
+
+<p>[</p>
+
+<p>]</p>
+
+<p>(</p>
+
+<p>)</p>
+
+<p>#</p>
+
+<p>+</p>
+
+<p>-</p>
+
+<p>.</p>
+
+<p>!</p>
diff --git a/test/script/markdown/github-style-at-start.js b/test/script/markdown/github-style-at-start.js
new file mode 100644
index 00000000..053f504a
--- /dev/null
+++ b/test/script/markdown/github-style-at-start.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "```\nfunction MyFunc(a) {\n // ...\n}\n```\n\nThat is some code!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/github-style-at-start.js.EXPECTED b/test/script/markdown/github-style-at-start.js.EXPECTED
new file mode 100644
index 00000000..4f119a76
--- /dev/null
+++ b/test/script/markdown/github-style-at-start.js.EXPECTED
@@ -0,0 +1,6 @@
+<pre><code>function MyFunc(a) {
+ // ...
+}
+</code></pre>
+
+<p>That is some code!</p>
diff --git a/test/script/markdown/github-style-codeblock.js b/test/script/markdown/github-style-codeblock.js
new file mode 100644
index 00000000..272f8ab2
--- /dev/null
+++ b/test/script/markdown/github-style-codeblock.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nDefine a function in javascript:\n\n```\nfunction MyFunc(a) {\n var s = '`';\n}\n```\n\nAnd some HTML\n\n```html\n<div>HTML!</div>\n```";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/github-style-codeblock.js.EXPECTED b/test/script/markdown/github-style-codeblock.js.EXPECTED
new file mode 100644
index 00000000..5daca2f9
--- /dev/null
+++ b/test/script/markdown/github-style-codeblock.js.EXPECTED
@@ -0,0 +1,11 @@
+<p>Define a function in javascript:</p>
+
+<pre><code>function MyFunc(a) {
+ var s = '`';
+}
+</code></pre>
+
+<p>And some HTML</p>
+
+<pre><code class="html">&lt;div&gt;HTML!&lt;/div&gt;
+</code></pre>
diff --git a/test/script/markdown/github-style-linebreaks.js b/test/script/markdown/github-style-linebreaks.js
new file mode 100644
index 00000000..17c739f5
--- /dev/null
+++ b/test/script/markdown/github-style-linebreaks.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "```\ncode can go here\nthis is rendered on a second line\n```";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/github-style-linebreaks.js.EXPECTED b/test/script/markdown/github-style-linebreaks.js.EXPECTED
new file mode 100644
index 00000000..276dbf03
--- /dev/null
+++ b/test/script/markdown/github-style-linebreaks.js.EXPECTED
@@ -0,0 +1,3 @@
+<pre><code>code can go here
+this is rendered on a second line
+</code></pre>
diff --git a/test/script/markdown/h1-with-double-hash.js b/test/script/markdown/h1-with-double-hash.js
new file mode 100644
index 00000000..7a822e55
--- /dev/null
+++ b/test/script/markdown/h1-with-double-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "# This is an H1 #";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h1-with-double-hash.js.EXPECTED b/test/script/markdown/h1-with-double-hash.js.EXPECTED
new file mode 100644
index 00000000..ab5b5555
--- /dev/null
+++ b/test/script/markdown/h1-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/test/script/markdown/h1-with-equals.js b/test/script/markdown/h1-with-equals.js
new file mode 100644
index 00000000..ec1b5a83
--- /dev/null
+++ b/test/script/markdown/h1-with-equals.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "This is an H1\n=============";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h1-with-equals.js.EXPECTED b/test/script/markdown/h1-with-equals.js.EXPECTED
new file mode 100644
index 00000000..ab5b5555
--- /dev/null
+++ b/test/script/markdown/h1-with-equals.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/test/script/markdown/h1-with-single-hash.js b/test/script/markdown/h1-with-single-hash.js
new file mode 100644
index 00000000..b878274d
--- /dev/null
+++ b/test/script/markdown/h1-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "# This is an H1";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h1-with-single-hash.js.EXPECTED b/test/script/markdown/h1-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..ab5b5555
--- /dev/null
+++ b/test/script/markdown/h1-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/test/script/markdown/h2-with-dashes.js b/test/script/markdown/h2-with-dashes.js
new file mode 100644
index 00000000..b5af2d36
--- /dev/null
+++ b/test/script/markdown/h2-with-dashes.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "This is an H2\n-------------";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h2-with-dashes.js.EXPECTED b/test/script/markdown/h2-with-dashes.js.EXPECTED
new file mode 100644
index 00000000..375a0d06
--- /dev/null
+++ b/test/script/markdown/h2-with-dashes.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/test/script/markdown/h2-with-double-hash.js b/test/script/markdown/h2-with-double-hash.js
new file mode 100644
index 00000000..0f7725fa
--- /dev/null
+++ b/test/script/markdown/h2-with-double-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "## This is an H2 ##";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h2-with-double-hash.js.EXPECTED b/test/script/markdown/h2-with-double-hash.js.EXPECTED
new file mode 100644
index 00000000..375a0d06
--- /dev/null
+++ b/test/script/markdown/h2-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/test/script/markdown/h2-with-single-hash.js b/test/script/markdown/h2-with-single-hash.js
new file mode 100644
index 00000000..29fb1c99
--- /dev/null
+++ b/test/script/markdown/h2-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "## This is an H2";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h2-with-single-hash.js.EXPECTED b/test/script/markdown/h2-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..375a0d06
--- /dev/null
+++ b/test/script/markdown/h2-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/test/script/markdown/h3-with-double-hash.js b/test/script/markdown/h3-with-double-hash.js
new file mode 100644
index 00000000..4e0eab8d
--- /dev/null
+++ b/test/script/markdown/h3-with-double-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "### This is an H3 ###";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h3-with-double-hash.js.EXPECTED b/test/script/markdown/h3-with-double-hash.js.EXPECTED
new file mode 100644
index 00000000..13f8c9e7
--- /dev/null
+++ b/test/script/markdown/h3-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h3 id="thisisanh3">This is an H3</h3>
diff --git a/test/script/markdown/h3-with-single-hash.js b/test/script/markdown/h3-with-single-hash.js
new file mode 100644
index 00000000..ab815eb7
--- /dev/null
+++ b/test/script/markdown/h3-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "### This is an H3";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h3-with-single-hash.js.EXPECTED b/test/script/markdown/h3-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..13f8c9e7
--- /dev/null
+++ b/test/script/markdown/h3-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h3 id="thisisanh3">This is an H3</h3>
diff --git a/test/script/markdown/h4-with-single-hash.js b/test/script/markdown/h4-with-single-hash.js
new file mode 100644
index 00000000..38d73670
--- /dev/null
+++ b/test/script/markdown/h4-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "#### This is an H4";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h4-with-single-hash.js.EXPECTED b/test/script/markdown/h4-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..165b4ef2
--- /dev/null
+++ b/test/script/markdown/h4-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h4 id="thisisanh4">This is an H4</h4>
diff --git a/test/script/markdown/h5-with-single-hash.js b/test/script/markdown/h5-with-single-hash.js
new file mode 100644
index 00000000..4a3d8395
--- /dev/null
+++ b/test/script/markdown/h5-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "##### This is an H5";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h5-with-single-hash.js.EXPECTED b/test/script/markdown/h5-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..28eac148
--- /dev/null
+++ b/test/script/markdown/h5-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h5 id="thisisanh5">This is an H5</h5>
diff --git a/test/script/markdown/h6-with-single-hash.js b/test/script/markdown/h6-with-single-hash.js
new file mode 100644
index 00000000..4a90f5c8
--- /dev/null
+++ b/test/script/markdown/h6-with-single-hash.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "###### This is an H6";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/h6-with-single-hash.js.EXPECTED b/test/script/markdown/h6-with-single-hash.js.EXPECTED
new file mode 100644
index 00000000..47574cc5
--- /dev/null
+++ b/test/script/markdown/h6-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h6 id="thisisanh6">This is an H6</h6>
diff --git a/test/script/markdown/horizontal-rules.js b/test/script/markdown/horizontal-rules.js
new file mode 100644
index 00000000..cec71571
--- /dev/null
+++ b/test/script/markdown/horizontal-rules.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n* * *\n\n***\n\n*****\n\n- - -\n\n---------------------------------------\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/horizontal-rules.js.EXPECTED b/test/script/markdown/horizontal-rules.js.EXPECTED
new file mode 100644
index 00000000..aaef23eb
--- /dev/null
+++ b/test/script/markdown/horizontal-rules.js.EXPECTED
@@ -0,0 +1,9 @@
+<hr />
+
+<hr />
+
+<hr />
+
+<hr />
+
+<hr />
diff --git a/test/script/markdown/html5-strutural-tags.js b/test/script/markdown/html5-strutural-tags.js
new file mode 100644
index 00000000..ad27c876
--- /dev/null
+++ b/test/script/markdown/html5-strutural-tags.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThese HTML5 tags should pass through just fine.\n\n<section>hello</section>\n<header>head</header>\n<footer>footsies</footer>\n<nav>navigation</nav>\n<article>read me</article>\n<aside>ignore me</aside>\n<article>read\nme</article>\n<aside>\nignore me\n</aside>\n\nthe end";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/html5-strutural-tags.js.EXPECTED b/test/script/markdown/html5-strutural-tags.js.EXPECTED
new file mode 100644
index 00000000..528731f5
--- /dev/null
+++ b/test/script/markdown/html5-strutural-tags.js.EXPECTED
@@ -0,0 +1,22 @@
+<p>These HTML5 tags should pass through just fine.</p>
+
+<section>hello</section>
+
+<header>head</header>
+
+<footer>footsies</footer>
+
+<nav>navigation</nav>
+
+<article>read me</article>
+
+<aside>ignore me</aside>
+
+<article>read
+me</article>
+
+<aside>
+ignore me
+</aside>
+
+<p>the end</p>
diff --git a/test/script/markdown/images.js b/test/script/markdown/images.js
new file mode 100644
index 00000000..4d52d61d
--- /dev/null
+++ b/test/script/markdown/images.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n![Alt text](/path/to/img.jpg)\n\n![Alt text](/path/to/img.jpg \"Optional title\")\n\n![Alt text][id]\n\n [id]: url/to/image \"Optional title attribute\"";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/images.js.EXPECTED b/test/script/markdown/images.js.EXPECTED
new file mode 100644
index 00000000..7df58552
--- /dev/null
+++ b/test/script/markdown/images.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><img src="/path/to/img.jpg" alt="Alt text" title="" /></p>
+
+<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
+
+<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>
diff --git a/test/script/markdown/implicit-anchors.js b/test/script/markdown/implicit-anchors.js
new file mode 100644
index 00000000..11d4bdbc
--- /dev/null
+++ b/test/script/markdown/implicit-anchors.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nSearch the web at [Google][] or [Daring Fireball][].\n\n [Google]: http://google.com/\n [Daring Fireball]: http://daringfireball.net/";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/implicit-anchors.js.EXPECTED b/test/script/markdown/implicit-anchors.js.EXPECTED
new file mode 100644
index 00000000..01e62d9a
--- /dev/null
+++ b/test/script/markdown/implicit-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.</p>
diff --git a/test/script/markdown/inline-anchors.js b/test/script/markdown/inline-anchors.js
new file mode 100644
index 00000000..8b18e0db
--- /dev/null
+++ b/test/script/markdown/inline-anchors.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThis is [an example](http://example.com/ \"Title\") inline link.\n\n[This link](http://example.net/) has no title attribute.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/inline-anchors.js.EXPECTED b/test/script/markdown/inline-anchors.js.EXPECTED
new file mode 100644
index 00000000..52f90ed3
--- /dev/null
+++ b/test/script/markdown/inline-anchors.js.EXPECTED
@@ -0,0 +1,3 @@
+<p>This is <a href="http://example.com/" title="Title">an example</a> inline link.</p>
+
+<p><a href="http://example.net/">This link</a> has no title attribute.</p>
diff --git a/test/script/markdown/inline-code.js b/test/script/markdown/inline-code.js
new file mode 100644
index 00000000..78fe9d7c
--- /dev/null
+++ b/test/script/markdown/inline-code.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nCreate a new `function`.\n\nUse the backtick in MySQL syntax ``SELECT `column` FROM whatever``.\n\nA single backtick in a code span: `` ` ``\n\nA backtick-delimited string in a code span: `` `foo` ``\n\nPlease don't use any `<blink>` tags.\n\n`&#8212;` is the decimal-encoded equivalent of `&mdash;`.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/inline-code.js.EXPECTED b/test/script/markdown/inline-code.js.EXPECTED
new file mode 100644
index 00000000..ebb7fdc0
--- /dev/null
+++ b/test/script/markdown/inline-code.js.EXPECTED
@@ -0,0 +1,11 @@
+<p>Create a new <code>function</code>.</p>
+
+<p>Use the backtick in MySQL syntax <code>SELECT `column` FROM whatever</code>.</p>
+
+<p>A single backtick in a code span: <code>`</code></p>
+
+<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
+
+<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
+
+<p><code>&amp;#8212;</code> is the decimal-encoded equivalent of <code>&amp;mdash;</code>.</p>
diff --git a/test/script/markdown/inline-style-tag.js b/test/script/markdown/inline-style-tag.js
new file mode 100644
index 00000000..5123e0ee
--- /dev/null
+++ b/test/script/markdown/inline-style-tag.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n<style>\n p { line-height: 20px; }\n</style>\n\nAn exciting sentence.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/inline-style-tag.js.EXPECTED b/test/script/markdown/inline-style-tag.js.EXPECTED
new file mode 100644
index 00000000..1006aa8f
--- /dev/null
+++ b/test/script/markdown/inline-style-tag.js.EXPECTED
@@ -0,0 +1,5 @@
+<style>
+ p { line-height: 20px; }
+</style>
+
+<p>An exciting sentence.</p>
diff --git a/test/script/markdown/lazy-blockquote.js b/test/script/markdown/lazy-blockquote.js
new file mode 100644
index 00000000..c857957e
--- /dev/null
+++ b/test/script/markdown/lazy-blockquote.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n > This is a multi line blockquote test\n\n > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/lazy-blockquote.js.EXPECTED b/test/script/markdown/lazy-blockquote.js.EXPECTED
new file mode 100644
index 00000000..c4956bbe
--- /dev/null
+++ b/test/script/markdown/lazy-blockquote.js.EXPECTED
@@ -0,0 +1,5 @@
+<blockquote>
+ <p>This is a multi line blockquote test</p>
+
+ <p>With more than one line.</p>
+</blockquote>
diff --git a/test/script/markdown/list-with-blockquote.js b/test/script/markdown/list-with-blockquote.js
new file mode 100644
index 00000000..8caf22e2
--- /dev/null
+++ b/test/script/markdown/list-with-blockquote.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "* A list item with a blockquote:\n\n > This is a blockquote\n > inside a list item.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/list-with-blockquote.js.EXPECTED b/test/script/markdown/list-with-blockquote.js.EXPECTED
new file mode 100644
index 00000000..7f18f5c1
--- /dev/null
+++ b/test/script/markdown/list-with-blockquote.js.EXPECTED
@@ -0,0 +1,8 @@
+<ul>
+<li><p>A list item with a blockquote:</p>
+
+<blockquote>
+ <p>This is a blockquote
+ inside a list item.</p>
+</blockquote></li>
+</ul>
diff --git a/test/script/markdown/list-with-code.js b/test/script/markdown/list-with-code.js
new file mode 100644
index 00000000..5d226d5e
--- /dev/null
+++ b/test/script/markdown/list-with-code.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "* A list item with code:\n\n alert('Hello world!');";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/list-with-code.js.EXPECTED b/test/script/markdown/list-with-code.js.EXPECTED
new file mode 100644
index 00000000..566fdae9
--- /dev/null
+++ b/test/script/markdown/list-with-code.js.EXPECTED
@@ -0,0 +1,6 @@
+<ul>
+<li><p>A list item with code:</p>
+
+<pre><code>alert('Hello world!');
+</code></pre></li>
+</ul>
diff --git a/test/script/markdown/multi-paragraph-list.js b/test/script/markdown/multi-paragraph-list.js
new file mode 100644
index 00000000..842e6a7a
--- /dev/null
+++ b/test/script/markdown/multi-paragraph-list.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n 1. This is a major bullet point.\n\n That contains multiple paragraphs.\n\n 2. And another line";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/multi-paragraph-list.js.EXPECTED b/test/script/markdown/multi-paragraph-list.js.EXPECTED
new file mode 100644
index 00000000..3d751c50
--- /dev/null
+++ b/test/script/markdown/multi-paragraph-list.js.EXPECTED
@@ -0,0 +1,6 @@
+<ol>
+<li><p>This is a major bullet point.</p>
+
+<p>That contains multiple paragraphs.</p></li>
+<li><p>And another line</p></li>
+</ol>
diff --git a/test/script/markdown/multiline-unordered-list.js b/test/script/markdown/multiline-unordered-list.js
new file mode 100644
index 00000000..77671b7b
--- /dev/null
+++ b/test/script/markdown/multiline-unordered-list.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n - This line spans\n more than one line and is lazy\n - Similar to this line";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/multiline-unordered-list.js.EXPECTED b/test/script/markdown/multiline-unordered-list.js.EXPECTED
new file mode 100644
index 00000000..fb2a58e0
--- /dev/null
+++ b/test/script/markdown/multiline-unordered-list.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>This line spans
+more than one line and is lazy</li>
+<li>Similar to this line</li>
+</ul>
diff --git a/test/script/markdown/nested-blockquote.js b/test/script/markdown/nested-blockquote.js
new file mode 100644
index 00000000..b6925c33
--- /dev/null
+++ b/test/script/markdown/nested-blockquote.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n > This is a multi line blockquote test\n >\n > > And nesting!\n >\n > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/nested-blockquote.js.EXPECTED b/test/script/markdown/nested-blockquote.js.EXPECTED
new file mode 100644
index 00000000..0b004934
--- /dev/null
+++ b/test/script/markdown/nested-blockquote.js.EXPECTED
@@ -0,0 +1,9 @@
+<blockquote>
+ <p>This is a multi line blockquote test</p>
+
+ <blockquote>
+ <p>And nesting!</p>
+ </blockquote>
+
+ <p>With more than one line.</p>
+</blockquote>
diff --git a/test/script/markdown/ordered-list-same-number.js b/test/script/markdown/ordered-list-same-number.js
new file mode 100644
index 00000000..5b4f97b8
--- /dev/null
+++ b/test/script/markdown/ordered-list-same-number.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n 1. Red\n 1. Green\n 1. Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/ordered-list-same-number.js.EXPECTED b/test/script/markdown/ordered-list-same-number.js.EXPECTED
new file mode 100644
index 00000000..b1abb536
--- /dev/null
+++ b/test/script/markdown/ordered-list-same-number.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/test/script/markdown/ordered-list-wrong-numbers.js b/test/script/markdown/ordered-list-wrong-numbers.js
new file mode 100644
index 00000000..56c4cea3
--- /dev/null
+++ b/test/script/markdown/ordered-list-wrong-numbers.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n 8. Red\n 1. Green\n 3. Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED b/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED
new file mode 100644
index 00000000..b1abb536
--- /dev/null
+++ b/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/test/script/markdown/ordered-list.js b/test/script/markdown/ordered-list.js
new file mode 100644
index 00000000..0316f2d5
--- /dev/null
+++ b/test/script/markdown/ordered-list.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n 1. Red\n 2. Green\n 3. Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/ordered-list.js.EXPECTED b/test/script/markdown/ordered-list.js.EXPECTED
new file mode 100644
index 00000000..b1abb536
--- /dev/null
+++ b/test/script/markdown/ordered-list.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/test/script/markdown/relative-anchors.js b/test/script/markdown/relative-anchors.js
new file mode 100644
index 00000000..b9938f33
--- /dev/null
+++ b/test/script/markdown/relative-anchors.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nSee my [About](/about/) page for details.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/relative-anchors.js.EXPECTED b/test/script/markdown/relative-anchors.js.EXPECTED
new file mode 100644
index 00000000..6db73dc4
--- /dev/null
+++ b/test/script/markdown/relative-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p>See my <a href="/about/">About</a> page for details.</p>
diff --git a/test/script/markdown/simple-paragraph.js b/test/script/markdown/simple-paragraph.js
new file mode 100644
index 00000000..e7bcd7dd
--- /dev/null
+++ b/test/script/markdown/simple-paragraph.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nHello, world!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/simple-paragraph.js.EXPECTED b/test/script/markdown/simple-paragraph.js.EXPECTED
new file mode 100644
index 00000000..7ce53543
--- /dev/null
+++ b/test/script/markdown/simple-paragraph.js.EXPECTED
@@ -0,0 +1 @@
+<p>Hello, world!</p>
diff --git a/test/script/markdown/strong.js b/test/script/markdown/strong.js
new file mode 100644
index 00000000..5f2a089b
--- /dev/null
+++ b/test/script/markdown/strong.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n**important**\n\n__important__\n\nreally **freaking**strong";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/strong.js.EXPECTED b/test/script/markdown/strong.js.EXPECTED
new file mode 100644
index 00000000..5bcc6756
--- /dev/null
+++ b/test/script/markdown/strong.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><strong>important</strong></p>
+
+<p><strong>important</strong></p>
+
+<p>really <strong>freaking</strong>strong</p>
diff --git a/test/script/markdown/table-basic.js b/test/script/markdown/table-basic.js
new file mode 100644
index 00000000..69909486
--- /dev/null
+++ b/test/script/markdown/table-basic.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "| First Header | Second Header |\n| ------------- | ------------- |\n| Row 1 Cell 1 | Row 1 Cell 2 |\n| Row 2 Cell 1 | Row 2 Cell 2 |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/table-basic.js.EXPECTED b/test/script/markdown/table-basic.js.EXPECTED
new file mode 100644
index 00000000..d909e65b
--- /dev/null
+++ b/test/script/markdown/table-basic.js.EXPECTED
@@ -0,0 +1,21 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/test/script/markdown/table-large.js b/test/script/markdown/table-large.js
new file mode 100644
index 00000000..28c55e52
--- /dev/null
+++ b/test/script/markdown/table-large.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "| First Header | Second Header | Third Header | Fourth Header |\n| ------------- | ------------- | ------------ | ------------- |\n| Row 1 Cell 1 | Row 1 Cell 2 | Row 1 Cell 3 | Row 1 Cell 4 |\n| Row 2 Cell 1 | Row 2 Cell 2 | Row 2 Cell 3 | Row 2 Cell 4 |\n| Row 3 Cell 1 | Row 3 Cell 2 | Row 3 Cell 3 | Row 3 Cell 4 |\n| Row 4 Cell 1 | Row 4 Cell 2 | Row 4 Cell 3 | Row 4 Cell 4 |\n| Row 5 Cell 1 | Row 5 Cell 2 | Row 5 Cell 3 | Row 5 Cell 4 |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/table-large.js.EXPECTED b/test/script/markdown/table-large.js.EXPECTED
new file mode 100644
index 00000000..332bdab6
--- /dev/null
+++ b/test/script/markdown/table-large.js.EXPECTED
@@ -0,0 +1,48 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+<th id="third_header" style="text-align:left;"> Third Header </th>
+<th id="fourth_header" style="text-align:left;"> Fourth Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 3 </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 4 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 3 </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 4 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 3 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 2 </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 3 </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 4 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 4 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 2 </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 3 </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 4 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 5 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 2 </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 3 </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 4 </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/test/script/markdown/table-with-equals.js b/test/script/markdown/table-with-equals.js
new file mode 100644
index 00000000..7d1283f3
--- /dev/null
+++ b/test/script/markdown/table-with-equals.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "| First Header | Second Header |\n| ============= | ============= |\n| Row 1 Cell 1 | Row 1 Cell 2 |\n| Row 2 Cell 1 | Row 2 Cell 2 |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/table-with-equals.js.EXPECTED b/test/script/markdown/table-with-equals.js.EXPECTED
new file mode 100644
index 00000000..d909e65b
--- /dev/null
+++ b/test/script/markdown/table-with-equals.js.EXPECTED
@@ -0,0 +1,21 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/test/script/markdown/unordered-list-asterisk.js b/test/script/markdown/unordered-list-asterisk.js
new file mode 100644
index 00000000..3c421f0d
--- /dev/null
+++ b/test/script/markdown/unordered-list-asterisk.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n * Red\n * Green\n * Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/unordered-list-asterisk.js.EXPECTED b/test/script/markdown/unordered-list-asterisk.js.EXPECTED
new file mode 100644
index 00000000..b445990a
--- /dev/null
+++ b/test/script/markdown/unordered-list-asterisk.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/test/script/markdown/unordered-list-minus.js b/test/script/markdown/unordered-list-minus.js
new file mode 100644
index 00000000..0867cc0e
--- /dev/null
+++ b/test/script/markdown/unordered-list-minus.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n - Red\n - Green\n - Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/unordered-list-minus.js.EXPECTED b/test/script/markdown/unordered-list-minus.js.EXPECTED
new file mode 100644
index 00000000..b445990a
--- /dev/null
+++ b/test/script/markdown/unordered-list-minus.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/test/script/markdown/unordered-list-plus.js b/test/script/markdown/unordered-list-plus.js
new file mode 100644
index 00000000..ac77b617
--- /dev/null
+++ b/test/script/markdown/unordered-list-plus.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\n + Red\n + Green\n + Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/unordered-list-plus.js.EXPECTED b/test/script/markdown/unordered-list-plus.js.EXPECTED
new file mode 100644
index 00000000..b445990a
--- /dev/null
+++ b/test/script/markdown/unordered-list-plus.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/test/script/markdown/url-with-parenthesis.js b/test/script/markdown/url-with-parenthesis.js
new file mode 100644
index 00000000..01ab472d
--- /dev/null
+++ b/test/script/markdown/url-with-parenthesis.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Test for Showdown markdown parser work with Nashorn.
+ *
+ * @test
+ * @run
+ */
+
+var input = "\nThere's an [episode](http://en.memory-alpha.org/wiki/Darmok_(episode)) of Star Trek: The Next Generation";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/test/script/markdown/url-with-parenthesis.js.EXPECTED b/test/script/markdown/url-with-parenthesis.js.EXPECTED
new file mode 100644
index 00000000..9e1e7cc9
--- /dev/null
+++ b/test/script/markdown/url-with-parenthesis.js.EXPECTED
@@ -0,0 +1 @@
+<p>There's an <a href="http://en.memory-alpha.org/wiki/Darmok_(episode)">episode</a> of Star Trek: The Next Generation</p>
diff --git a/test/script/nosecurity/JDK-8044798.js b/test/script/nosecurity/JDK-8044798.js
index dc1a7478..c24edf21 100644
--- a/test/script/nosecurity/JDK-8044798.js
+++ b/test/script/nosecurity/JDK-8044798.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,6 +25,8 @@
* JDK-8044798: API for debugging Nashorn
*
* @test
+ * @option -Dnashorn.mirror.always=false
+ * @fork
* @run
*/
@@ -37,11 +39,7 @@ var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.
var valueDescFields = DebuggerValueDesc.class.declaredFields;
Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name));
-var keyField;
for each (var f in valueDescFields) {
- if (f.name == "key") {
- keyField = f;
- }
f.accessible = true;
}
@@ -92,22 +90,18 @@ for each (var f in valueDescFields) {
// valueInfos
var infos = valueInfosMethod.invoke(null, Object, true);
-Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2)));
-
for each (var info in infos) {
for each (var f in valueDescFields) {
print(f.name, "=", f.get(info));
- }
+ }
}
// valueInfos - user defined object
var infos = valueInfosMethod.invoke(null, { foo: 34, bar: "hello" }, true);
-Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2)));
-
for each (var info in infos) {
for each (var f in valueDescFields) {
print(f.name, "=", f.get(info));
- }
+ }
}
// valueAsString
diff --git a/test/script/nosecurity/JDK-8044798.js.EXPECTED b/test/script/nosecurity/JDK-8044798.js.EXPECTED
index 2a21328c..24d82818 100644
--- a/test/script/nosecurity/JDK-8044798.js.EXPECTED
+++ b/test/script/nosecurity/JDK-8044798.js.EXPECTED
@@ -8,54 +8,74 @@ key = foo
valueAsObject = [object Object]
valueAsString = {foo: 343}
expandable = false
-key = bindProperties
-valueAsObject = function bindProperties() { [native code] }
-valueAsString = function bindProperties() { [native code] }
+key = setIndexedPropertiesToExternalArrayData
+valueAsObject = function setIndexedPropertiesToExternalArrayData() { [native code] }
+valueAsString = function setIndexedPropertiesToExternalArrayData() { [native code] }
+expandable = false
+key = getPrototypeOf
+valueAsObject = function getPrototypeOf() { [native code] }
+valueAsString = function getPrototypeOf() { [native code] }
+expandable = false
+key = setPrototypeOf
+valueAsObject = function setPrototypeOf() { [native code] }
+valueAsString = function setPrototypeOf() { [native code] }
+expandable = false
+key = getOwnPropertyDescriptor
+valueAsObject = function getOwnPropertyDescriptor() { [native code] }
+valueAsString = function getOwnPropertyDescriptor() { [native code] }
+expandable = false
+key = getOwnPropertyNames
+valueAsObject = function getOwnPropertyNames() { [native code] }
+valueAsString = function getOwnPropertyNames() { [native code] }
expandable = false
key = create
valueAsObject = function create() { [native code] }
valueAsString = function create() { [native code] }
expandable = false
+key = defineProperty
+valueAsObject = function defineProperty() { [native code] }
+valueAsString = function defineProperty() { [native code] }
+expandable = false
key = defineProperties
valueAsObject = function defineProperties() { [native code] }
valueAsString = function defineProperties() { [native code] }
expandable = false
-key = defineProperty
-valueAsObject = function defineProperty() { [native code] }
-valueAsString = function defineProperty() { [native code] }
+key = seal
+valueAsObject = function seal() { [native code] }
+valueAsString = function seal() { [native code] }
expandable = false
key = freeze
valueAsObject = function freeze() { [native code] }
valueAsString = function freeze() { [native code] }
expandable = false
-key = getOwnPropertyDescriptor
-valueAsObject = function getOwnPropertyDescriptor() { [native code] }
-valueAsString = function getOwnPropertyDescriptor() { [native code] }
-expandable = false
-key = getOwnPropertyNames
-valueAsObject = function getOwnPropertyNames() { [native code] }
-valueAsString = function getOwnPropertyNames() { [native code] }
-expandable = false
-key = getPrototypeOf
-valueAsObject = function getPrototypeOf() { [native code] }
-valueAsString = function getPrototypeOf() { [native code] }
+key = preventExtensions
+valueAsObject = function preventExtensions() { [native code] }
+valueAsString = function preventExtensions() { [native code] }
expandable = false
-key = isExtensible
-valueAsObject = function isExtensible() { [native code] }
-valueAsString = function isExtensible() { [native code] }
+key = isSealed
+valueAsObject = function isSealed() { [native code] }
+valueAsString = function isSealed() { [native code] }
expandable = false
key = isFrozen
valueAsObject = function isFrozen() { [native code] }
valueAsString = function isFrozen() { [native code] }
expandable = false
-key = isSealed
-valueAsObject = function isSealed() { [native code] }
-valueAsString = function isSealed() { [native code] }
+key = isExtensible
+valueAsObject = function isExtensible() { [native code] }
+valueAsString = function isExtensible() { [native code] }
expandable = false
key = keys
valueAsObject = function keys() { [native code] }
valueAsString = function keys() { [native code] }
expandable = false
+key = bindProperties
+valueAsObject = function bindProperties() { [native code] }
+valueAsString = function bindProperties() { [native code] }
+expandable = false
+key = prototype
+valueAsObject = [object Object]
+valueAsString = {toString: function toString() { [native code] }, toLocaleString: function toLocaleString() { [native code] }, valueOf: function valueOf() { [native code] }, hasOwnProperty: function hasOwnProperty() { [native code] }, isPrototypeOf: function isPrototypeOf() { [native code] }, propertyIsEnumerable: function propertyIsEnumerable() { [native code] }, constructor: function Object() { [native code] }, __proto__: null}
+expandable = false
key = length
valueAsObject = 1
valueAsString = 1
@@ -64,33 +84,13 @@ key = name
valueAsObject = Object
valueAsString = "Object"
expandable = false
-key = preventExtensions
-valueAsObject = function preventExtensions() { [native code] }
-valueAsString = function preventExtensions() { [native code] }
-expandable = false
-key = prototype
-valueAsObject = [object Object]
-valueAsString = {toString: function toString() { [native code] }, toLocaleString: function toLocaleString() { [native code] }, valueOf: function valueOf() { [native code] }, hasOwnProperty: function hasOwnProperty() { [native code] }, isPrototypeOf: function isPrototypeOf() { [native code] }, propertyIsEnumerable: function propertyIsEnumerable() { [native code] }, constructor: function Object() { [native code] }, __proto__: null}
-expandable = false
-key = seal
-valueAsObject = function seal() { [native code] }
-valueAsString = function seal() { [native code] }
-expandable = false
-key = setIndexedPropertiesToExternalArrayData
-valueAsObject = function setIndexedPropertiesToExternalArrayData() { [native code] }
-valueAsString = function setIndexedPropertiesToExternalArrayData() { [native code] }
-expandable = false
-key = setPrototypeOf
-valueAsObject = function setPrototypeOf() { [native code] }
-valueAsString = function setPrototypeOf() { [native code] }
+key = foo
+valueAsObject = 34
+valueAsString = 34
expandable = false
key = bar
valueAsObject = hello
valueAsString = "hello"
-expandable = false
-key = foo
-valueAsObject = 34
-valueAsString = 34
undefined
null
"hello"
diff --git a/test/script/nosecurity/JDK-8044851.js b/test/script/nosecurity/JDK-8044851.js
new file mode 100644
index 00000000..679c3491
--- /dev/null
+++ b/test/script/nosecurity/JDK-8044851.js
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8044851: nashorn properties leak memory
+ *
+ * @test
+ * @run
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+function printProperty(value, property) {
+ print(value, property.getKey(), property.isSpill() ? "spill" : "field", property.getSlot());
+}
+
+var obj = {}, i, name;
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ obj[name] = 'a' + i;
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ obj[name] = 'b' + i;
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}, configurable: true});
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ obj[name] = 'c' + i;
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 7; i > -1; --i) {
+ name = 'property' + i;
+ delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ obj[name] = 'd' + i;
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+ name = 'property' + i;
+ Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}});
+ printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
diff --git a/test/script/nosecurity/JDK-8044851.js.EXPECTED b/test/script/nosecurity/JDK-8044851.js.EXPECTED
new file mode 100644
index 00000000..4b8ca441
--- /dev/null
+++ b/test/script/nosecurity/JDK-8044851.js.EXPECTED
@@ -0,0 +1,53 @@
+a0 property0 field 0
+a1 property1 field 1
+a2 property2 field 2
+a3 property3 field 3
+a4 property4 spill 0
+a5 property5 spill 1
+a6 property6 spill 2
+a7 property7 spill 3
+
+b0 property0 field 0
+b1 property1 field 1
+b2 property2 field 2
+b3 property3 field 3
+b4 property4 spill 0
+b5 property5 spill 1
+b6 property6 spill 2
+b7 property7 spill 3
+
+0 property0 spill 4
+1 property1 spill 5
+2 property2 spill 6
+3 property3 spill 7
+4 property4 spill 8
+5 property5 spill 0
+6 property6 spill 1
+7 property7 spill 2
+
+c0 property0 field 0
+c1 property1 field 1
+c2 property2 field 2
+c3 property3 field 3
+c4 property4 spill 0
+c5 property5 spill 1
+c6 property6 spill 2
+c7 property7 spill 3
+
+d0 property0 field 0
+d1 property1 field 1
+d2 property2 field 2
+d3 property3 field 3
+d4 property4 spill 0
+d5 property5 spill 1
+d6 property6 spill 2
+d7 property7 spill 3
+
+0 property0 spill 4
+1 property1 spill 5
+2 property2 spill 6
+3 property3 spill 7
+4 property4 spill 8
+5 property5 spill 0
+6 property6 spill 1
+7 property7 spill 2
diff --git a/test/script/nosecurity/JDK-8050964.js b/test/script/nosecurity/JDK-8050964.js
new file mode 100644
index 00000000..eda3d1b6
--- /dev/null
+++ b/test/script/nosecurity/JDK-8050964.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8050964: OptimisticTypesPersistence.java should use java.util.Date instead of java.sql.Date
+ *
+ * Make sure that nashorn.jar has only 'compact1' dependency.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// assume that this script is run with "nashorn.jar" System
+// property set to relative path of nashorn.jar from the current
+// directory of test execution.
+
+if (typeof fail != 'function') {
+ fail = print;
+}
+
+var System = java.lang.System;
+var File = java.io.File;
+var nashornJar = new File(System.getProperty("nashorn.jar"));
+if (! nashornJar.isAbsolute()) {
+ nashornJar = new File(".", nashornJar);
+}
+
+var javahome = System.getProperty("java.home");
+var jdepsPath = javahome + "/../bin/jdeps".replaceAll(/\//g, File.separater);
+
+// run jdep on nashorn.jar - only summary but print profile info
+$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
+`${jdepsPath} -s -P ${nashornJar.absolutePath}`
+
+// check for "(compact1)" in output from jdep tool
+if (! /(compact1)/.test($OUT)) {
+ fail("non-compact1 dependency: " + $OUT);
+}
diff --git a/test/script/nosecurity/JDK-8055034.js b/test/script/nosecurity/JDK-8055034.js
new file mode 100644
index 00000000..a0e5057e
--- /dev/null
+++ b/test/script/nosecurity/JDK-8055034.js
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055034: jjs exits interactive mode if exception was thrown when trying to print value of last evaluated expression
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// assume that this script is run with "nashorn.jar" System
+// property set to relative or absolute path of nashorn.jar
+
+if (typeof fail != 'function') {
+ fail = print;
+}
+
+var System = java.lang.System;
+var File = java.io.File;
+var javahome = System.getProperty("java.home");
+var nashornJar = new File(System.getProperty("nashorn.jar"));
+if (! nashornJar.isAbsolute()) {
+ nashornJar = new File(".", nashornJar);
+}
+var nashornJarDir = nashornJar.parentFile.absolutePath;
+
+// we want to use nashorn.jar passed and not the one that comes with JRE
+var jjsCmd = javahome + "/../bin/jjs";
+jjsCmd += " -J-Djava.ext.dirs=" + nashornJarDir;
+jjsCmd = jjsCmd.toString().replaceAll(/\//g, File.separater);
+$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
+$EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
+
+// $ERR has all interactions including prompts! Just check for error substring.
+var err = $ERR.trim();
+if (! err.contains("TypeError: Cannot get default string value")) {
+ fail("Error stream does not contain expected error message");
+}
+
+// should print "PASSED"
+print($OUT.trim());
+// exit code should be 0
+print("exit code = " + $EXIT);
diff --git a/test/script/nosecurity/JDK-8055034.js.EXPECTED b/test/script/nosecurity/JDK-8055034.js.EXPECTED
new file mode 100644
index 00000000..416340d4
--- /dev/null
+++ b/test/script/nosecurity/JDK-8055034.js.EXPECTED
@@ -0,0 +1,2 @@
+PASSED
+exit code = 0
diff --git a/test/script/nosecurity/JDK-8055107.js b/test/script/nosecurity/JDK-8055107.js
new file mode 100644
index 00000000..bcc3cba2
--- /dev/null
+++ b/test/script/nosecurity/JDK-8055107.js
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
+ *
+ * @test
+ * @option -Dnashorn.debug=true
+ * @option -scripting
+ * @run
+ * @fork
+ */
+
+function runScriptEngine(code) {
+ var imports = new JavaImporter(
+ java.io, java.lang, java.util, javax.script);
+
+ with(imports) {
+ var m = new ScriptEngineManager();
+ // get current System.err
+ var oldErr = System.err;
+ var baos = new ByteArrayOutputStream();
+ var newErr = new PrintStream(baos);
+ try {
+ // set new standard err
+ System.setErr(newErr);
+ var engine = m.getEngineByName("nashorn");
+ engine.eval(code);
+ newErr.flush();
+ return new java.lang.String(baos.toByteArray());
+ } finally {
+ // restore System.err to old value
+ System.setErr(oldErr);
+ }
+ }
+}
+
+// nashorn callsite trace enterexit
+var str = runScriptEngine(<<CODE
+function func() {
+ "nashorn callsite trace enterexit";
+ k();
+}
+
+function k() {
+ var x = "hello";
+}
+
+func();
+CODE);
+
+if (!str.contains(" ENTER ")) {
+ fail("expected 'ENTER' in trace mode output");
+}
+
+if (!str.contains(" EXIT ")) {
+ fail("expected 'EXIT' in trace mode output");
+}
+
+// nashorn callsite trace objects
+var str = runScriptEngine(<<CODE
+"nashorn callsite trace objects";
+function func(x) {
+}
+
+func("hello");
+CODE);
+
+if (!str.contains(" ENTER ")) {
+ fail("expected 'ENTER' in trace mode output");
+}
+
+if (!str.contains(" EXIT ")) {
+ fail("expected 'EXIT' in trace mode output");
+}
+
+if (!str.contains("hello")) {
+ fail("expected argument to be traced in trace objects mode");
+}
+
+// nashorn callsite trace misses
+str = runScriptEngine(<<CODE
+function f() {
+ "nashorn callsite trace misses";
+ k();
+}
+
+function k() {}
+f();
+CODE);
+
+if (!str.contains(" MISS ")) {
+ fail("expected callsite MISS trace messages");
+}
+
+// nashorn print lower ast
+str = runScriptEngine(<<CODE
+function foo() {
+ "nashorn print lower ast";
+ var x = 'hello';
+}
+foo();
+CODE);
+
+if (!str.contains("Lower AST for: 'foo'") ||
+ !str.contains("nashorn print lower ast")) {
+ fail("expected Lower AST to be printed for 'foo'");
+}
+
+// nashorn print ast
+str = runScriptEngine(<<CODE
+function foo() {
+ "nashorn print ast";
+}
+CODE);
+if (!str.contains("[function ") ||
+ !str.contains("nashorn print ast")) {
+ fail("expected AST to be printed");
+}
+
+// nashorn print symbols
+str = runScriptEngine(<<CODE
+function bar(a) {
+ "nashorn print symbols";
+ if (a) print(a);
+}
+
+bar();
+CODE)
+
+if (!str.contains("[BLOCK in 'Function bar']")) {
+ fail("expected symbols to be printed for 'bar'");
+}
+
+// nashorn print parse
+str = runScriptEngine(<<CODE
+"nashorn print parse";
+
+function func() {}
+CODE);
+
+if (!str.contains("function func") ||
+ !str.contains("nashorn print parse")) {
+ fail("expected nashorn print parse output");
+}
+
+// nashorn print lower parse
+str = runScriptEngine(<<CODE
+"nashorn print lower parse";
+
+function func() {}
+
+func()
+CODE);
+
+if (!str.contains("function {U%}func") ||
+ !str.contains("nashorn print lower parse")) {
+ fail("expected nashorn print lower parse output");
+}
diff --git a/test/script/nosecurity/JDK-8060688.js b/test/script/nosecurity/JDK-8060688.js
new file mode 100644
index 00000000..8fe57814
--- /dev/null
+++ b/test/script/nosecurity/JDK-8060688.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8060688: Nashorn: Generated script class name fails --verify-code for names with special chars
+ *
+ * @test
+ * @run
+ */
+
+var NashornEngineFactory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
+var ScriptEngine = Java.type("javax.script.ScriptEngine");
+var ScriptContext = Java.type("javax.script.ScriptContext");
+
+var factory = new NashornEngineFactory();
+
+var e = factory.getScriptEngine("--verify-code");
+
+function evalAndCheck(code) {
+ try {
+ e.eval(code);
+ } catch (exp) {
+ exp.printStackTrace();
+ }
+}
+
+// check default name
+evalAndCheck("var a = 3");
+// check few names with special chars
+var scontext = e.context;
+scontext.setAttribute(ScriptEngine.FILENAME, "<myscript>", ScriptContext.ENGINE_SCOPE);
+evalAndCheck("var h = 'hello'");
+scontext.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE);
+evalAndCheck("var foo = 'world'");
+scontext.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE);
+evalAndCheck("var foo = 'helloworld'");
diff --git a/test/script/nosecurity/debuggersupportapi.js b/test/script/nosecurity/debuggersupportapi.js
index f2fa1014..db4a69a8 100644
--- a/test/script/nosecurity/debuggersupportapi.js
+++ b/test/script/nosecurity/debuggersupportapi.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/nosecurity/nosecurity.js b/test/script/nosecurity/nosecurity.js
index 688af8cf..b35171b7 100644
--- a/test/script/nosecurity/nosecurity.js
+++ b/test/script/nosecurity/nosecurity.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * 8043443: Test framework changes to run script tests without security manager
+ * 8043443: Test framework changes to run script tests without security manager
* @test
* @run
*/
diff --git a/test/script/sandbox/JDK-8031106.js b/test/script/sandbox/JDK-8031106.js
index d5d83f69..26d15a2a 100644
--- a/test/script/sandbox/JDK-8031106.js
+++ b/test/script/sandbox/JDK-8031106.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/NASHORN-525.js b/test/script/sandbox/NASHORN-525.js
index c6a0d4fc..a099b449 100644
--- a/test/script/sandbox/NASHORN-525.js
+++ b/test/script/sandbox/NASHORN-525.js
@@ -1,28 +1,28 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
- * NASHORN-525 : nashorn misses security access checks
+ * NASHORN-525 : nashorn misses security access checks
*
* @test
* @run
diff --git a/test/script/sandbox/arrayclass.js b/test/script/sandbox/arrayclass.js
index c29c86bd..69996dc0 100644
--- a/test/script/sandbox/arrayclass.js
+++ b/test/script/sandbox/arrayclass.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/classbind.js b/test/script/sandbox/classbind.js
index 2dabb3e2..05e12928 100644
--- a/test/script/sandbox/classbind.js
+++ b/test/script/sandbox/classbind.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/classloader.js b/test/script/sandbox/classloader.js
index 9de1a5c3..36cf464c 100644
--- a/test/script/sandbox/classloader.js
+++ b/test/script/sandbox/classloader.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/doprivileged.js b/test/script/sandbox/doprivileged.js
index d901347d..5b08361f 100644
--- a/test/script/sandbox/doprivileged.js
+++ b/test/script/sandbox/doprivileged.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -48,11 +48,11 @@ AccessController.doPrivileged(new PrivilegedAction() {
check(e);
}
- try {
- var prop = java.lang.System.getProperty("user.dir");
+ try {
+ var prop = java.lang.System.getProperty("user.dir");
fail("can get user.dir " + prop);
- } catch(e) {
+ } catch(e) {
print(e);
- }
+ }
}
});
diff --git a/test/script/sandbox/engine.js b/test/script/sandbox/engine.js
index e1d87c78..77aa36e8 100644
--- a/test/script/sandbox/engine.js
+++ b/test/script/sandbox/engine.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/env.js b/test/script/sandbox/env.js
index df80e6fb..5ef40a2d 100644
--- a/test/script/sandbox/env.js
+++ b/test/script/sandbox/env.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/exec.js b/test/script/sandbox/exec.js
index 86d70b36..0f32938e 100644
--- a/test/script/sandbox/exec.js
+++ b/test/script/sandbox/exec.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/exit.js b/test/script/sandbox/exit.js
index d77744fe..b807c976 100644
--- a/test/script/sandbox/exit.js
+++ b/test/script/sandbox/exit.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/file.js b/test/script/sandbox/file.js
index dce3afd0..3aaa8978 100644
--- a/test/script/sandbox/file.js
+++ b/test/script/sandbox/file.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/interfaceimpl.js b/test/script/sandbox/interfaceimpl.js
index b2ee86b5..0745318c 100644
--- a/test/script/sandbox/interfaceimpl.js
+++ b/test/script/sandbox/interfaceimpl.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/javaextend.js b/test/script/sandbox/javaextend.js
index 60eab74d..a2d18333 100644
--- a/test/script/sandbox/javaextend.js
+++ b/test/script/sandbox/javaextend.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -30,7 +30,7 @@ function model(n) {
return Java.type("jdk.nashorn.test.models." + n)
}
-// Can't extend a final class
+// Can't extend a final class
try {
Java.extend(model("FinalClass"))
} catch(e) {
diff --git a/test/script/sandbox/jsadapter.js b/test/script/sandbox/jsadapter.js
index 32bedc8c..494b900f 100644
--- a/test/script/sandbox/jsadapter.js
+++ b/test/script/sandbox/jsadapter.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/loadLibrary.js b/test/script/sandbox/loadLibrary.js
index 1e5151f0..e693d222 100644
--- a/test/script/sandbox/loadLibrary.js
+++ b/test/script/sandbox/loadLibrary.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/loadcompat.js b/test/script/sandbox/loadcompat.js
index f0338df7..0dfa9444 100644
--- a/test/script/sandbox/loadcompat.js
+++ b/test/script/sandbox/loadcompat.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/nashorninternals.js b/test/script/sandbox/nashorninternals.js
index c68b6c8d..d68f3f36 100644
--- a/test/script/sandbox/nashorninternals.js
+++ b/test/script/sandbox/nashorninternals.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
- * Test to check that nashorn "internal" classes in codegen, parser, ir
+ * Test to check that nashorn "internal" classes in codegen, parser, ir
* packages cannot * be accessed from sandbox scripts.
*
* @test
diff --git a/test/script/sandbox/net.js b/test/script/sandbox/net.js
index 37aaf578..c7fd8d01 100644
--- a/test/script/sandbox/net.js
+++ b/test/script/sandbox/net.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/property.js b/test/script/sandbox/property.js
index 685cf329..8aeb499e 100644
--- a/test/script/sandbox/property.js
+++ b/test/script/sandbox/property.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/reflection.js b/test/script/sandbox/reflection.js
index 4fdc58fd..225f4440 100644
--- a/test/script/sandbox/reflection.js
+++ b/test/script/sandbox/reflection.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -38,5 +38,5 @@ function check(e) {
try {
var cl = java.lang.Class.class;
} catch(e) {
- check(e);
+ check(e);
}
diff --git a/test/script/sandbox/runnable.js b/test/script/sandbox/runnable.js
index 75f533b6..02c8b4aa 100644
--- a/test/script/sandbox/runnable.js
+++ b/test/script/sandbox/runnable.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/sandbox/unsafe.js b/test/script/sandbox/unsafe.js
index 6b3f43af..57f9d48f 100644
--- a/test/script/sandbox/unsafe.js
+++ b/test/script/sandbox/unsafe.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -43,7 +43,7 @@ try {
}
try {
- var unsafe = Java.type("sun.misc.Unsafe");
+ var unsafe = Java.type("sun.misc.Unsafe");
fail("No SecurityException for Java.type sun.misc.Unsafe");
} catch (e) {
check(e);
diff --git a/test/script/test262.js b/test/script/test262.js
index a03e612b..8ca528c8 100644
--- a/test/script/test262.js
+++ b/test/script/test262.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/test262_single.js b/test/script/test262_single.js
index 2cc905ec..86d0b421 100644
--- a/test/script/test262_single.js
+++ b/test/script/test262_single.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/JDK-8006424.js b/test/script/trusted/JDK-8006424.js
index 88516e13..fa0dabde 100644
--- a/test/script/trusted/JDK-8006424.js
+++ b/test/script/trusted/JDK-8006424.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/JDK-8006529.js b/test/script/trusted/JDK-8006529.js
index 3567c33e..5f618074 100644
--- a/test/script/trusted/JDK-8006529.js
+++ b/test/script/trusted/JDK-8006529.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -33,16 +33,18 @@
* This test script depends on nashorn Compiler internals. It uses reflection
* to get access to private field and many public methods of Compiler and
* FunctionNode classes. Note that this is trusted code and access to such
- * internal package classes and methods is okay. But, if you modify any
+ * internal package classes and methods is okay. But, if you modify any
* Compiler or FunctionNode class, you may have to revisit this script.
* We cannot use direct Java class (via dynalink bean linker) to Compiler
* and FunctionNode because of package-access check and so reflective calls.
*/
-var forName = java.lang.Class["forName(String)"];
+var forName = java.lang.Class["forName(String)"];
var Parser = forName("jdk.nashorn.internal.parser.Parser").static
var Compiler = forName("jdk.nashorn.internal.codegen.Compiler").static
+var CompilationPhases = forName("jdk.nashorn.internal.codegen.Compiler$CompilationPhases").static;
var Context = forName("jdk.nashorn.internal.runtime.Context").static
+var CodeInstaller = forName("jdk.nashorn.internal.runtime.CodeInstaller").static
var ScriptEnvironment = forName("jdk.nashorn.internal.runtime.ScriptEnvironment").static
var Source = forName("jdk.nashorn.internal.runtime.Source").static
var FunctionNode = forName("jdk.nashorn.internal.ir.FunctionNode").static
@@ -54,20 +56,23 @@ var BinaryNode = forName("jdk.nashorn.internal.ir.BinaryNode").static
var ThrowErrorManager = forName("jdk.nashorn.internal.runtime.Context$ThrowErrorManager").static
var ErrorManager = forName("jdk.nashorn.internal.runtime.ErrorManager").static
var Debug = forName("jdk.nashorn.internal.runtime.Debug").static
+var String = forName("java.lang.String").static
+var boolean = Java.type("boolean");
var parseMethod = Parser.class.getMethod("parse");
-var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class);
+var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class, CompilationPhases.class);
var getBodyMethod = FunctionNode.class.getMethod("getBody");
var getStatementsMethod = Block.class.getMethod("getStatements");
var getInitMethod = VarNode.class.getMethod("getInit");
var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
-var rhsMethod = UnaryNode.class.getMethod("rhs")
+var rhsMethod = UnaryNode.class.getMethod("getExpression")
var lhsMethod = BinaryNode.class.getMethod("lhs")
var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
+var compilePhases = CompilationPhases.class.getField("COMPILE_UPTO_BYTECODE").get(null);
// These are method names of methods in FunctionNode class
-var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'needsSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
+var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'usesSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
// corresponding Method objects of FunctionNode class
var functionNodeMethods = {};
@@ -103,8 +108,8 @@ function findFunction(node) {
return findFunction(rhsMethod.invoke(node))
} else if(node instanceof BinaryNode) {
return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
- } else if(node instanceof ExpressionStatement) {
- return findFunction(getExpressionMethod.invoke(node))
+ } else if(node instanceof ExpressionStatement) {
+ return findFunction(getExpressionMethod.invoke(node))
} else if(node instanceof FunctionNode) {
return node
}
@@ -115,22 +120,23 @@ var getEnvMethod = Context.class.getMethod("getEnv")
var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
-var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
+var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class);
-// compile(script) -- compiles a script specified as a string with its
-// source code, returns a jdk.nashorn.internal.ir.FunctionNode object
+// compile(script) -- compiles a script specified as a string with its
+// source code, returns a jdk.nashorn.internal.ir.FunctionNode object
// representing it.
-function compile(source) {
+function compile(source, phases) {
var source = sourceForMethod.invoke(null, "<no name>", source);
- var env = getEnvMethod.invoke(getContextMethod.invoke(null))
+ var ctxt = getContextMethod.invoke(null);
+ var env = getEnvMethod.invoke(ctxt);
var parser = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
var func = parseMethod.invoke(parser);
- var compiler = CompilerConstructor.newInstance(env);
+ var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false);
- return compileMethod.invoke(compiler, func);
+ return compileMethod.invoke(compiler, func, phases);
};
var allAssertions = (function() {
@@ -166,8 +172,8 @@ function test(f) {
// assertions are true in the first function in the given script; "script"
// is a string with the source text of the script.
function testFirstFn(script) {
- arguments[0] = getFirstFunction(compile(script))
- test.apply(null, arguments)
+ arguments[0] = getFirstFunction(compile(script, compilePhases));
+ test.apply(null, arguments);
}
// ---------------------------------- ACTUAL TESTS START HERE --------------
@@ -197,13 +203,13 @@ testFirstFn("function f() { function arguments() {}; arguments; }")
// A function defining "arguments" as a local variable will be vararg.
testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
-// A self-referencing function defined as a statement doesn't need a self
+// A self-referencing function defined as a statement doesn't need a self
// symbol, as it'll rather obtain itself from the parent scope.
testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
// A self-referencing function defined as an expression needs a self symbol,
// as it can't obtain itself from the parent scope.
-testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
+testFirstFn("(function f() { f() })", 'needsCallee', 'usesSelfSymbol')
// A child function accessing parent's variable triggers the need for scope
// in parent
@@ -217,7 +223,7 @@ testFirstFn("(function f(x) { function g() { x } })", 'hasScopeBlock')
// scope in parent
testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
-// A child function redefining a local variable from its parent should not
+// A child function redefining a local variable from its parent should not
// affect the parent function in any way
testFirstFn("(function f() { var x; function g() { var x; x } })")
@@ -239,14 +245,15 @@ testFirstFn("(function f() { var x; function g() { var o; with(o) { x } } })", '
// Using "eval" triggers pretty much everything. The function even needs to be
// vararg, 'cause we don't know if eval will be using "arguments".
-testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
+testFirstFn("(function f() { eval() })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
// Nested function using "eval" is almost the same as parent function using
// eval, but at least the parent doesn't have to be vararg.
-testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
+testFirstFn("(function f() { function g() { eval() } })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
// Function with 250 named parameters is ordinary
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 }")
// Function with 251 named parameters is variable arguments
-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')
+// NOTE: hasScopeBlock should be optimized away. Implementation of JDK-8038942 should take care of it.
+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')
diff --git a/test/script/trusted/JDK-8008305.js b/test/script/trusted/JDK-8008305.js
index d57b5208..d75561b4 100644
--- a/test/script/trusted/JDK-8008305.js
+++ b/test/script/trusted/JDK-8008305.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/JDK-8008305_subtest.js b/test/script/trusted/JDK-8008305_subtest.js
index 2485f39d..b88ed3c5 100644
--- a/test/script/trusted/JDK-8008305_subtest.js
+++ b/test/script/trusted/JDK-8008305_subtest.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/JDK-8020809.js b/test/script/trusted/JDK-8020809.js
index 6e0296c6..9052ff04 100644
--- a/test/script/trusted/JDK-8020809.js
+++ b/test/script/trusted/JDK-8020809.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* JDK-8020809: Java adapter should not allow overriding of caller sensitive methods
- *
+ *
* @test
* @run
*/
diff --git a/test/script/trusted/JDK-8021129.js b/test/script/trusted/JDK-8021129.js
index 93bf12ab..47ad5d42 100644
--- a/test/script/trusted/JDK-8021129.js
+++ b/test/script/trusted/JDK-8021129.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -25,7 +25,7 @@
* JDK-8021129: Test prevention of access to members of restricted classes.
* Note that even though the script runs as trusted, we still don't allow
* access to non-public portions of restricted classes.
- *
+ *
* @test
* @run
*/
diff --git a/test/script/trusted/JDK-8021189.js b/test/script/trusted/JDK-8021189.js
index 528a21b6..c4c93cb9 100644
--- a/test/script/trusted/JDK-8021189.js
+++ b/test/script/trusted/JDK-8021189.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -23,7 +23,7 @@
/**
* JDK-8021189: Prevent access to constructors of restricted classes
- *
+ *
* @test
* @run
*/
diff --git a/test/script/trusted/JDK-8025629.js b/test/script/trusted/JDK-8025629.js
index 7dda8465..609cfe8b 100644
--- a/test/script/trusted/JDK-8025629.js
+++ b/test/script/trusted/JDK-8025629.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/JDK-8032060.js b/test/script/trusted/JDK-8032060.js
index 8cb350cc..4a3fe249 100644
--- a/test/script/trusted/JDK-8032060.js
+++ b/test/script/trusted/JDK-8032060.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/NASHORN-638.js b/test/script/trusted/NASHORN-638.js
index 1ff789a9..0bd5d41f 100644
--- a/test/script/trusted/NASHORN-638.js
+++ b/test/script/trusted/NASHORN-638.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/NASHORN-653.js b/test/script/trusted/NASHORN-653.js
index 14a2cbc4..b6d9a544 100644
--- a/test/script/trusted/NASHORN-653.js
+++ b/test/script/trusted/NASHORN-653.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
@@ -35,37 +35,37 @@ function a() { \
\
function b() { \
while (x) { \
- return true; \
+ return true; \
} \
} \
\
function c() { \
while (true) { \
- return true; \
+ return true; \
} \
} \
\
function d() { \
do { \
- return true; \
+ return true; \
} while (x); \
} \
\
function f() { \
for (;;) { \
- return true; \
+ return true; \
} \
} \
\
function e() { \
for (;;) { \
- return true; \
+ return true; \
} \
} \
\
function g() { \
for(;;) { \
- print('goes on and on and on ... '); \
+ print('goes on and on and on ... '); \
} \
print('x'); \
} \
diff --git a/test/script/trusted/classfilter.js b/test/script/trusted/classfilter.js
new file mode 100644
index 00000000..a50e4a2c
--- /dev/null
+++ b/test/script/trusted/classfilter.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * ClassFilter to filter out java classes in a script engine.
+ *
+ * @test
+ * @run
+ */
+
+var NashornScriptEngineFactory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
+
+var fac = new NashornScriptEngineFactory();
+// allow only "java.*" classes to be accessed
+var e = fac.getScriptEngine(
+ function(name) name.startsWith("java."));
+
+function evalIt(str) {
+ print(str + " evalutes to " + e.eval(str));
+}
+
+function evalExpectError(str) {
+ try {
+ print(e.eval(str));
+ fail("expected error for: " + str);
+ } catch(exp) {
+ print(str + " throws " + exp);
+ }
+}
+
+evalIt("typeof javax.script.ScriptContext");
+evalIt("typeof javax.script.ScriptEngine");
+evalIt("typeof java.util.Vector");
+evalIt("typeof java.util.Map");
+evalIt("typeof java.util.HashMap");
+// should be able to call methods, create objects of java.* classes
+evalIt("var m = new java.util.HashMap(); m.put('foo', 42); m");
+evalIt("java.lang.System.out.println");
+evalIt("java.lang.System.exit");
+
+evalExpectError("new javax.script.SimpleBindings");
+evalExpectError("Java.type('javax.script.ScriptContext')");
+evalExpectError("java.lang.Class.forName('javax.script.ScriptContext')");
+
+try {
+ fac["getScriptEngine(ClassFilter)"](null);
+ fail("should have thrown NPE");
+} catch (e) {
+ if (! (e instanceof java.lang.NullPointerException)) {
+ fail("NPE expected, got " + e);
+ }
+}
diff --git a/test/script/trusted/classfilter.js.EXPECTED b/test/script/trusted/classfilter.js.EXPECTED
new file mode 100644
index 00000000..43d63039
--- /dev/null
+++ b/test/script/trusted/classfilter.js.EXPECTED
@@ -0,0 +1,11 @@
+typeof javax.script.ScriptContext evalutes to object
+typeof javax.script.ScriptEngine evalutes to object
+typeof java.util.Vector evalutes to function
+typeof java.util.Map evalutes to function
+typeof java.util.HashMap evalutes to function
+var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42}
+java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println]
+java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)]
+new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings
+Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext
+java.lang.Class.forName('javax.script.ScriptContext') throws javax.script.ScriptException: TypeError: Java reflection not supported when class filter is present in <eval> at line number 1
diff --git a/test/script/trusted/classfilter_extends.js b/test/script/trusted/classfilter_extends.js
new file mode 100644
index 00000000..e721b3a1
--- /dev/null
+++ b/test/script/trusted/classfilter_extends.js
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987
+ * @run
+ */
+
+var factory = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory')
+var engine = new factory().getScriptEngine(function(str){
+ return str.indexOf('java.lang.Class') != -1
+ || str == 'java.lang.System'
+ || str.indexOf('java.util') != -1;
+})
+
+function tryEval (str) {
+ try {
+ print(eval(str))
+ print(engine.eval(str))
+ } catch (exc) {
+ print(exc.message)
+ }
+}
+
+tryEval("Java.type('java.util.ArrayList')")
+tryEval("Java.type('java.lang.String')")
+tryEval("java.util.ArrayList")
+tryEval("java.lang.String")
+tryEval("Java.extend(java.util.ArrayList, {})")
+tryEval("Java.extend(java.io.File, {})")
+tryEval("new java.lang.NullPointerException();")
+tryEval("try { java.lang.System.load(null) } catch (e) { e }")
diff --git a/test/script/trusted/classfilter_extends.js.EXPECTED b/test/script/trusted/classfilter_extends.js.EXPECTED
new file mode 100644
index 00000000..e0cf856b
--- /dev/null
+++ b/test/script/trusted/classfilter_extends.js.EXPECTED
@@ -0,0 +1,16 @@
+[JavaClass java.util.ArrayList]
+[JavaClass java.util.ArrayList]
+[JavaClass java.lang.String]
+java.lang.ClassNotFoundException: java.lang.String
+[JavaClass java.util.ArrayList]
+[JavaClass java.util.ArrayList]
+[JavaClass java.lang.String]
+[JavaPackage java.lang.String]
+[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java.io.File]
+TypeError: Java.extend needs Java types as its arguments. in <eval> at line number 1
+java.lang.NullPointerException
+java.lang.ClassNotFoundException: java.lang.NullPointerException
+java.lang.NullPointerException: library can't be null
+java.lang.NullPointerException: library can't be null
diff --git a/test/script/trusted/classfilter_mozilla_compat.js b/test/script/trusted/classfilter_mozilla_compat.js
new file mode 100644
index 00000000..cb05a3d7
--- /dev/null
+++ b/test/script/trusted/classfilter_mozilla_compat.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8036987
+ * @run
+ */
+
+var factory = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory')
+var engine = new factory().getScriptEngine(function(str){
+ return str.indexOf('java.util') != -1;
+})
+
+load("nashorn:mozilla_compat.js");
+engine.eval("load('nashorn:mozilla_compat.js');")
+
+function tryEval (str) {
+ try {
+ print(eval(str))
+ print(engine.eval(str))
+ } catch (exc) {
+ print(exc.message)
+ }
+}
+
+tryEval("new JavaAdapter(javax.script.ScriptContext){}.class")
+tryEval("new JavaAdapter(java.util.ArrayList){}.class")
+tryEval("importClass(java.lang.Integer); Integer")
+tryEval("importClass(java.util.HashSet); HashSet")
+tryEval("importPackage(java.lang); Integer")
+tryEval("importPackage(java.util); HashMap")
diff --git a/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED b/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
new file mode 100644
index 00000000..9481e98e
--- /dev/null
+++ b/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
@@ -0,0 +1,12 @@
+class javax.script.ScriptContext$$NashornJavaAdapter
+TypeError: Java.extend needs at least one type argument. in nashorn:mozilla_compat.js at line number 39
+class jdk.nashorn.javaadapters.java.util.ArrayList
+class jdk.nashorn.javaadapters.java.util.ArrayList
+[JavaClass java.lang.Integer]
+TypeError: [object JavaPackage] is not a Java class in nashorn:mozilla_compat.js at line number 373 at column number 16
+[JavaClass java.util.HashSet]
+[JavaClass java.util.HashSet]
+[JavaClass java.lang.Integer]
+ReferenceError: "Integer" is not defined in nashorn:mozilla_compat.js at line number 67
+[JavaClass java.util.HashMap]
+[JavaClass java.util.HashMap]
diff --git a/test/script/trusted/event_queue.js b/test/script/trusted/event_queue.js
new file mode 100644
index 00000000..feecc201
--- /dev/null
+++ b/test/script/trusted/event_queue.js
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Debug.eventqueue test - instead of screen scraping, test the concept of asking Debug for
+ * an event log of favourable events.
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.debug=true
+ * @option --log=recompile:quiet
+ * @option --optimistic-types=true
+ */
+
+print(Debug);
+print();
+
+var forName = java.lang.Class["forName(String)"];
+var RuntimeEvent = forName("jdk.nashorn.internal.runtime.events.RuntimeEvent").static;
+var getValue = RuntimeEvent.class.getMethod("getValue");
+var getValueClass = RuntimeEvent.class.getMethod("getValueClass");
+
+print(RuntimeEvent);
+
+var RewriteException = forName("jdk.nashorn.internal.runtime.RewriteException").static;
+var getReturnType = RewriteException.class.getMethod("getReturnType");
+
+print(RewriteException);
+
+var a = [1.1, 2.2];
+function f() {
+ var sum = 2;
+ for (var i = 0; i < a.length; i++) {
+ sum *= a[i];
+ }
+ return sum;
+}
+
+function g() {
+ var diff = 17;
+ for (var i = 0; i < a.length; i++) {
+ diff -= a[i];
+ }
+ return diff;
+}
+
+//kill anything that may already be in the event queue from earlier debug runs
+Debug.clearRuntimeEvents();
+
+print();
+print(f());
+print(g());
+
+print();
+events = Debug.getRuntimeEvents();
+print("Done with " + events.length + " in the event queue");
+//make sure we got runtime events
+print("events = " + (events.toString().indexOf("RuntimeEvent") != -1));
+print("events.length = " + events.length);
+
+var lastInLoop = undefined;
+for (var i = 0; i < events.length; i++) {
+ var e = events[i];
+ print("event #" + i);
+ print("\tevent class=" + e.getClass());
+ print("\tvalueClass in event=" + getValueClass.invoke(e));
+ var v = getValue.invoke(e);
+ print("\tclass of value=" + v.getClass());
+ print("\treturn type=" + getReturnType.invoke(v));
+ lastInLoop = events[i];
+}
+
+print();
+print("in loop last class = " + lastInLoop.getClass());
+print("in loop last value class = " + getValueClass.invoke(lastInLoop));
+var rexInLoop = getValue.invoke(lastInLoop);
+print("in loop rex class = " + rexInLoop.getClass());
+print("in loop rex return type = " + getReturnType.invoke(rexInLoop));
+
+//try last runtime events
+var last = Debug.getLastRuntimeEvent();
+//the code after the loop creates additional rewrite exceptions
+print();
+print(last !== lastInLoop);
+print();
+
+print("last class = " + last.getClass());
+print("last value class = " + getValueClass.invoke(last));
+var rex = getValue.invoke(last);
+print("rex class = " + rex.getClass());
+print("rex return type = " + getReturnType.invoke(rex));
+
+//try the capacity setter
+print();
+print(Debug.getEventQueueCapacity());
+Debug.setEventQueueCapacity(2048);
+print(Debug.getEventQueueCapacity());
+
+//try clear events
+print();
+Debug.clearRuntimeEvents();
+print(Debug.getRuntimeEvents().length);
+
diff --git a/test/script/trusted/event_queue.js.EXPECTED b/test/script/trusted/event_queue.js.EXPECTED
new file mode 100644
index 00000000..d4eb7299
--- /dev/null
+++ b/test/script/trusted/event_queue.js.EXPECTED
@@ -0,0 +1,38 @@
+[object Debug]
+
+[JavaClass jdk.nashorn.internal.runtime.events.RuntimeEvent]
+[JavaClass jdk.nashorn.internal.runtime.RewriteException]
+
+4.840000000000001
+13.7
+
+Done with 2 in the event queue
+events = true
+events.length = 2
+event #0
+ event class=class jdk.nashorn.internal.runtime.events.RecompilationEvent
+ valueClass in event=class jdk.nashorn.internal.runtime.RewriteException
+ class of value=class jdk.nashorn.internal.runtime.RewriteException
+ return type=double
+event #1
+ event class=class jdk.nashorn.internal.runtime.events.RecompilationEvent
+ valueClass in event=class jdk.nashorn.internal.runtime.RewriteException
+ class of value=class jdk.nashorn.internal.runtime.RewriteException
+ return type=double
+
+in loop last class = class jdk.nashorn.internal.runtime.events.RecompilationEvent
+in loop last value class = class jdk.nashorn.internal.runtime.RewriteException
+in loop rex class = class jdk.nashorn.internal.runtime.RewriteException
+in loop rex return type = double
+
+true
+
+last class = class jdk.nashorn.internal.runtime.events.RecompilationEvent
+last value class = class jdk.nashorn.internal.runtime.RewriteException
+rex class = class jdk.nashorn.internal.runtime.RewriteException
+rex return type = object
+
+1024
+2048
+
+0
diff --git a/test/script/trusted/getenv.js b/test/script/trusted/getenv.js
index 9fb3a96e..29df8bac 100644
--- a/test/script/trusted/getenv.js
+++ b/test/script/trusted/getenv.js
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
- *
+ *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
- *
+ *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
diff --git a/test/script/trusted/optimistic_recompilation.js b/test/script/trusted/optimistic_recompilation.js
new file mode 100644
index 00000000..9c9a9c75
--- /dev/null
+++ b/test/script/trusted/optimistic_recompilation.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Ask Debug for an event log of favourable events instead of using --log flags printing to screen
+ * @test
+ * @bug 8037086,8038398
+ * @fork
+ * @option -Dnashorn.debug=true
+ * @option --log=recompile:quiet
+ * @option --optimistic-types=true
+ */
+
+var forName = java.lang.Class["forName(String)"];
+var RuntimeEvent = forName("jdk.nashorn.internal.runtime.events.RuntimeEvent").static;
+var getValue = RuntimeEvent.class.getMethod("getValue");
+var RewriteException = forName("jdk.nashorn.internal.runtime.RewriteException").static;
+var getReturnType = RewriteException.class.getMethod("getReturnType");
+var RecompilationEvent = forName("jdk.nashorn.internal.runtime.events.RecompilationEvent").static;
+var getReturnValue = RecompilationEvent.class.getMethod("getReturnValue");
+var setReturnTypeAndValue = [];
+var expectedValues = [];
+
+function checkExpectedRecompilation(f, expectedValues, testCase) {
+ Debug.clearRuntimeEvents();
+ print(f());
+ events = Debug.getRuntimeEvents();
+ //make sure we got runtime events
+ print("events = " + (events.toString().indexOf("RuntimeEvent") != -1));
+ if (events.length == expectedValues.length) {
+ for (var i in events) {
+ var e = events[i];
+ var returnValue = getReturnValue.invoke(e);
+ if (typeof returnValue != 'undefined') {
+ setReturnTypeAndValue[i] = [getReturnType.invoke(getValue.invoke(e)), returnValue];
+ } else {
+ returnValue = "undefined";
+ setReturnTypeAndValue[i] = [getReturnType.invoke(getValue.invoke(e)), returnValue];
+ }
+ if (!setReturnTypeAndValue[i].toString().equals(expectedValues[i].toString())) {
+ fail("The return values are not as expected. Expected value: " + expectedValues[i] + " and got: " + setReturnTypeAndValue[i] + " in test case: " + f);
+ }
+ }
+ } else {
+ fail("Number of Deoptimizing recompilation is not correct, expected: " + expectedValues.length + " and found: " + events.length + " in test case: " + f);
+ }
+}
+
+checkExpectedRecompilation(function divisionByZeroTest() {var x = { a: 2, b:1 }; x.a = Number.POSITIVE_INFINITY; x.b = 0; print(x.a/x.b); return 1;},
+ expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function divisionWithRemainderTest() {var x = { a: 7, b:2 }; print(x.a/x.b); return 1;}, expectedValues =[['double', '3.5']]);
+checkExpectedRecompilation(function infinityMultiplicationTest() {var x = { a: Number.POSITIVE_INFINITY, b: Number.POSITIVE_INFINITY}; print(x.a*x.b); return 1;},
+ expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function maxValueMultiplicationTest() {var x = { a: Number.MAX_VALUE, b: Number.MAX_VALUE}; print(x.a*x.b); return 1;},
+ expectedValues =[['double', '1.7976931348623157e+308']]);
+checkExpectedRecompilation(function divisionByInfinityTest() {var x = { a: -1, b: Number.POSITIVE_INFINITY}; print(x.a/x.b); return 1;},
+ expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function divisionByStringTest() {var x = { a: Number.POSITIVE_INFINITY, b: 'Hello'}; print(x.a/x.b); return 1;},
+ expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function nestedFunctionTest() {var a=3,b,c; function f() {var x = 2, y =1; function g(){var y = x; var z = a; z = x*y; print(a*b)} g()}f(); return 1;},
+ expectedValues =[['object', 'undefined']]);
+checkExpectedRecompilation(function functionTest(a,b,c) { d = (a + b) * c; print(d); return 1;}, expectedValues =[['double', 'NaN']]);
+checkExpectedRecompilation(function andTest(a,b) { d = a && b; print(d); return 1;}, expectedValues =[['object', 'undefined']]);
diff --git a/test/script/trusted/optimistic_recompilation.js.EXPECTED b/test/script/trusted/optimistic_recompilation.js.EXPECTED
new file mode 100644
index 00000000..b36497fb
--- /dev/null
+++ b/test/script/trusted/optimistic_recompilation.js.EXPECTED
@@ -0,0 +1,27 @@
+Infinity
+1
+events = true
+3.5
+1
+events = true
+Infinity
+1
+events = true
+Infinity
+1
+events = true
+0
+1
+events = true
+NaN
+1
+events = true
+NaN
+1
+events = true
+NaN
+1
+events = true
+undefined
+1
+events = true
diff --git a/test/src/UnnamedPackageTestCallback.java b/test/src/UnnamedPackageTestCallback.java
index 67ab36fc..3b6cdf5a 100644
--- a/test/src/UnnamedPackageTestCallback.java
+++ b/test/src/UnnamedPackageTestCallback.java
@@ -23,6 +23,14 @@
* questions.
*/
+/**
+ * Interface for callbacks used by the test suite.
+ */
public interface UnnamedPackageTestCallback {
+ /**
+ * Call function
+ * @param s string argument
+ * @return string
+ */
String call(String s);
}
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
new file mode 100644
index 00000000..d9a44551
--- /dev/null
+++ b/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.dynalink.beans;
+
+import jdk.nashorn.test.models.ClassLoaderAware;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class CallerSensitiveTest {
+ @Test
+ public void testCallerSensitive() {
+ BeansLinker.getLinkerForClass(ClassLoaderAware.class);
+ }
+}
diff --git a/test/src/jdk/nashorn/api/NashornSQLDriver.java b/test/src/jdk/nashorn/api/NashornSQLDriver.java
index 2987b948..dd624096 100644
--- a/test/src/jdk/nashorn/api/NashornSQLDriver.java
+++ b/test/src/jdk/nashorn/api/NashornSQLDriver.java
@@ -25,7 +25,12 @@
package jdk.nashorn.api;
-import java.sql.*;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;
@@ -36,18 +41,18 @@ public final class NashornSQLDriver implements Driver {
static {
try {
DriverManager.registerDriver(new NashornSQLDriver(), null);
- } catch (SQLException se) {
+ } catch (final SQLException se) {
throw new RuntimeException(se);
}
}
@Override
- public boolean acceptsURL(String url) {
+ public boolean acceptsURL(final String url) {
return url.startsWith("jdbc:nashorn:");
}
@Override
- public Connection connect(String url, Properties info) {
+ public Connection connect(final String url, final Properties info) {
throw new UnsupportedOperationException("I am a dummy!!");
}
@@ -62,7 +67,7 @@ public final class NashornSQLDriver implements Driver {
}
@Override
- public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
+ public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
return new DriverPropertyInfo[0];
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java b/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
index 4a1d8d5d..1da767b7 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
@@ -29,7 +29,6 @@ import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
-
import java.util.Arrays;
import java.util.List;
import javax.script.ScriptContext;
@@ -41,6 +40,7 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+@SuppressWarnings("javadoc")
public class ArrayConversionTest {
private static ScriptEngine e = null;
@@ -49,7 +49,7 @@ public class ArrayConversionTest {
}
@BeforeClass
- public static void setUpClass() throws ScriptException {
+ public static void setUpClass() {
e = new ScriptEngineManager().getEngineByName("nashorn");
}
@@ -111,25 +111,25 @@ public class ArrayConversionTest {
e.eval("Java.type('" + ArrayConversionTest.class.getName() + "')." + testMethodName + "(" + argument + ")");
}
- public static void assertNullIntArray(int[] array) {
+ public static void assertNullIntArray(final int[] array) {
assertNull(array);
}
- public static void assertNullIntIntArray(int[][] array) {
+ public static void assertNullIntIntArray(final int[][] array) {
assertNull(array);
}
- public static void assertEmptyIntArray(int[] array) {
+ public static void assertEmptyIntArray(final int[] array) {
assertEquals(0, array.length);
}
- public static void assertSingle42IntArray(int[] array) {
+ public static void assertSingle42IntArray(final int[] array) {
assertEquals(1, array.length);
assertEquals(42, array[0]);
}
- public static void assertIntArrayConversions(int[] array) {
+ public static void assertIntArrayConversions(final int[] array) {
assertEquals(13, array.length);
assertEquals(0, array[0]); // false
assertEquals(1, array[1]); // true
@@ -146,21 +146,21 @@ public class ArrayConversionTest {
assertEquals(0, array[12]); // [1, 2]
}
- public static void assertEmptyIntIntArray(int[][] array) {
+ public static void assertEmptyIntIntArray(final int[][] array) {
assertEquals(0, array.length);
}
- public static void assertSingleEmptyIntIntArray(int[][] array) {
+ public static void assertSingleEmptyIntIntArray(final int[][] array) {
assertEquals(1, array.length);
assertTrue(Arrays.equals(new int[0], array[0]));
}
- public static void assertSingleNullIntIntArray(int[][] array) {
+ public static void assertSingleNullIntIntArray(final int[][] array) {
assertEquals(1, array.length);
assertNull(null, array[0]);
}
- public static void assertLargeIntIntArray(int[][] array) {
+ public static void assertLargeIntIntArray(final int[][] array) {
assertEquals(5, array.length);
assertTrue(Arrays.equals(new int[] { 0 }, array[0]));
assertTrue(Arrays.equals(new int[] { 1 }, array[1]));
@@ -169,7 +169,7 @@ public class ArrayConversionTest {
assertTrue(Arrays.equals(new int[] { 7, 8 }, array[4]));
}
- public static void assertLargeObjectObjectArray(Object[][] array) throws ScriptException {
+ public static void assertLargeObjectObjectArray(final Object[][] array) throws ScriptException {
assertEquals(4, array.length);
assertTrue(Arrays.equals(new Object[] { Boolean.FALSE }, array[0]));
assertTrue(Arrays.equals(new Object[] { 1 }, array[1]));
@@ -179,7 +179,7 @@ public class ArrayConversionTest {
assertEquals(17, e.eval("obj.x"));
}
- public static void assertBooleanArrayConversions(boolean[] array) {
+ public static void assertBooleanArrayConversions(final boolean[] array) {
assertEquals(16, array.length);
assertFalse(array[0]); // false
assertTrue(array[1]); // true
@@ -199,26 +199,26 @@ public class ArrayConversionTest {
assertFalse(array[15]); // undefined
}
- public static void assertListArray(List<?>[] array) {
+ public static void assertListArray(final List<?>[] array) {
assertEquals(2, array.length);
assertEquals(Arrays.asList("foo", "bar"), array[0]);
assertEquals(Arrays.asList("apple", "orange"), array[1]);
}
- public static void assertVarArg_42_17(Object... args) throws ScriptException {
+ public static void assertVarArg_42_17(final Object... args) {
assertEquals(2, args.length);
assertEquals(42, ((Number)args[0]).intValue());
assertEquals(17, ((Number)args[1]).intValue());
}
- public static void assertVarArg_array_17(Object... args) throws ScriptException {
+ public static void assertVarArg_array_17(final Object... args) throws ScriptException {
assertEquals(2, args.length);
e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]);
assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42"));
assertEquals(18, ((Number)args[1]).intValue());
}
- public static void assertVarArg_function(Object... args) throws ScriptException {
+ public static void assertVarArg_function(final Object... args) throws ScriptException {
assertEquals(1, args.length);
e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]);
assertEquals("Hello", e.eval("fn()"));
@@ -226,10 +226,10 @@ public class ArrayConversionTest {
- public static void x(String y) {
+ public static void x(final String y) {
assertEquals("abc", y);
}
- public static void x(String[] y) {
+ public static void x(final String[] y) {
assertTrue(Arrays.equals(new String[] { "foo", "bar"}, y));
}
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java
index 19873564..234484f7 100644
--- a/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java
@@ -27,7 +27,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
-
import java.util.Arrays;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@@ -42,6 +41,7 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.BooleanAccessTest
* @run testng/othervm jdk.nashorn.api.javaaccess.BooleanAccessTest
*/
+@SuppressWarnings("javadoc")
public class BooleanAccessTest {
private static ScriptEngine e = null;
diff --git a/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java b/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
index 1eadfb77..2b12b046 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
@@ -26,7 +26,6 @@
package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
-
import java.util.HashMap;
import java.util.Map;
import javax.script.Bindings;
@@ -40,6 +39,7 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+@SuppressWarnings("javadoc")
public class ConsStringTest {
private static ScriptEngine e = null;
@@ -48,7 +48,7 @@ public class ConsStringTest {
}
@BeforeClass
- public static void setUpClass() throws ScriptException {
+ public static void setUpClass() {
e = new ScriptEngineManager().getEngineByName("nashorn");
}
@@ -69,7 +69,7 @@ public class ConsStringTest {
@Test
public void testConsStringFromMirror() throws ScriptException {
final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
- final Map<Object, Object> m = new HashMap<>();
+ //final Map<Object, Object> m = new HashMap<>();
e.eval("var x = 'f'; x += 'oo'; var obj = {x: x};");
assertEquals("foo", ((JSObject)b.get("obj")).getMember("x"));
}
@@ -88,7 +88,7 @@ public class ConsStringTest {
public static class ArrayHolder {
private Object[] array;
- public void setArray(Object[] array) {
+ public void setArray(final Object[] array) {
this.array = array;
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java
index 4be66b81..8bac7e6a 100644
--- a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java
@@ -28,7 +28,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
@@ -45,6 +44,7 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.MethodAccessTest
* @run testng/othervm jdk.nashorn.api.javaaccess.MethodAccessTest
*/
+@SuppressWarnings("javadoc")
public class MethodAccessTest {
private static ScriptEngine e = null;
diff --git a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
index 116d1cf4..fd4ab9da 100644
--- a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
@@ -28,7 +28,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
-
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
@@ -42,10 +41,11 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberAccessTest
* @run testng/othervm jdk.nashorn.api.javaaccess.NumberAccessTest
*/
+@SuppressWarnings("javadoc")
public class NumberAccessTest {
- private static ScriptEngine e = null;
- private static SharedObject o = null;
+ private static ScriptEngine e;
+ private static SharedObject o;
public static void main(final String[] args) {
TestNG.main(args);
@@ -264,7 +264,7 @@ public class NumberAccessTest {
@Test
public void accessFieldByte() throws ScriptException {
e.eval("var p_byte = o.publicByte;");
- assertEquals(o.publicByte, e.get("p_byte"));
+ assertEquals((double)o.publicByte, ((Number)e.get("p_byte")).doubleValue());
e.eval("o.publicByte = 16;");
assertEquals(16, o.publicByte);
}
@@ -287,7 +287,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFieldByte() throws ScriptException {
e.eval("var ps_byte = SharedObject.publicStaticByte;");
- assertEquals(SharedObject.publicStaticByte, e.get("ps_byte"));
+ assertEquals((double)SharedObject.publicStaticByte, ((Number)e.get("ps_byte")).doubleValue());
e.eval("SharedObject.publicStaticByte = 16;");
assertEquals(16, SharedObject.publicStaticByte);
}
@@ -310,7 +310,7 @@ public class NumberAccessTest {
@Test
public void accessFinalFieldByte() throws ScriptException {
e.eval("var pf_byte = o.publicFinalByte;");
- assertEquals(o.publicFinalByte, e.get("pf_byte"));
+ assertEquals((double)o.publicFinalByte, ((Number)e.get("pf_byte")).doubleValue());
e.eval("o.publicFinalByte = 16;");
assertEquals(-7, o.publicFinalByte);
}
@@ -333,7 +333,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFinalFieldByte() throws ScriptException {
e.eval("var psf_byte = SharedObject.publicStaticFinalByte;");
- assertEquals(SharedObject.publicStaticFinalByte, e.get("psf_byte"));
+ assertEquals((double)SharedObject.publicStaticFinalByte, ((Number)e.get("psf_byte")).doubleValue());
e.eval("SharedObject.publicStaticFinalByte = 16;");
assertEquals(-70, SharedObject.publicStaticFinalByte);
}
@@ -358,7 +358,7 @@ public class NumberAccessTest {
@Test
public void accessFieldShort() throws ScriptException {
e.eval("var p_short = o.publicShort;");
- assertEquals(o.publicShort, e.get("p_short"));
+ assertEquals((double)o.publicShort, ((Number)e.get("p_short")).doubleValue());
e.eval("o.publicShort = 18;");
assertEquals(18, o.publicShort);
}
@@ -381,7 +381,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFieldShort() throws ScriptException {
e.eval("var ps_short = SharedObject.publicStaticShort;");
- assertEquals(SharedObject.publicStaticShort, e.get("ps_short"));
+ assertEquals((double)SharedObject.publicStaticShort, ((Number)e.get("ps_short")).doubleValue());
e.eval("SharedObject.publicStaticShort = 180;");
assertEquals(180, SharedObject.publicStaticShort);
}
@@ -404,7 +404,7 @@ public class NumberAccessTest {
@Test
public void accessFinalFieldShort() throws ScriptException {
e.eval("var pf_short = o.publicFinalShort;");
- assertEquals(o.publicFinalShort, e.get("pf_short"));
+ assertEquals((double)o.publicFinalShort, ((Number)e.get("pf_short")).doubleValue());
e.eval("o.publicFinalShort = 180;");
assertEquals(31220, o.publicFinalShort);
}
@@ -427,7 +427,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFinalFieldShort() throws ScriptException {
e.eval("var psf_short = SharedObject.publicStaticFinalShort;");
- assertEquals(SharedObject.publicStaticFinalShort, e.get("psf_short"));
+ assertEquals((double)SharedObject.publicStaticFinalShort, ((Number)e.get("psf_short")).doubleValue());
e.eval("SharedObject.publicStaticFinalShort = 180;");
assertEquals(8888, SharedObject.publicStaticFinalShort);
}
@@ -555,7 +555,7 @@ public class NumberAccessTest {
@Test
public void accessFieldFloat() throws ScriptException {
e.eval("var p_float = o.publicFloat;");
- assertEquals(o.publicFloat, e.get("p_float"));
+ assertEquals((double)o.publicFloat, ((Number)e.get("p_float")).doubleValue());
o.publicFloat = 0.0f / 0.0f;
assertEquals(true, e.eval("isNaN(o.publicFloat)"));
o.publicFloat = 1.0f / 0.0f;
@@ -590,7 +590,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFieldFloat() throws ScriptException {
e.eval("var ps_float = SharedObject.publicStaticFloat;");
- assertEquals(SharedObject.publicStaticFloat, e.get("ps_float"));
+ assertEquals((double)SharedObject.publicStaticFloat, ((Number)e.get("ps_float")).doubleValue());
SharedObject.publicStaticFloat = 0.0f / 0.0f;
assertEquals(true, e.eval("isNaN(SharedObject.publicStaticFloat)"));
SharedObject.publicStaticFloat = 1.0f / 0.0f;
@@ -625,7 +625,7 @@ public class NumberAccessTest {
@Test
public void accessFinalFloat() throws ScriptException {
e.eval("var pf_float = o.publicFinalFloat;");
- assertEquals(o.publicFinalFloat, e.get("pf_float"));
+ assertEquals((double)o.publicFinalFloat, ((Number)e.get("pf_float")).doubleValue());
e.eval("o.publicFinalFloat = 20.0;");
assertEquals(7.72e8f, o.publicFinalFloat, 1e-10);
}
@@ -648,7 +648,7 @@ public class NumberAccessTest {
@Test
public void accessStaticFinalFieldFloat() throws ScriptException {
e.eval("var psf_float = SharedObject.publicStaticFinalFloat;");
- assertEquals(SharedObject.publicStaticFinalFloat, e.get("psf_float"));
+ assertEquals((double)SharedObject.publicStaticFinalFloat, ((Number)e.get("psf_float")).doubleValue());
e.eval("SharedObject.publicStaticFinalFloat = 20.0;");
assertEquals(0.72e8f, SharedObject.publicStaticFinalFloat, 1e-10);
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java b/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
index 03e30752..40db6845 100644
--- a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
@@ -27,7 +27,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
-
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
@@ -41,10 +40,11 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberBoxingTest
* @run testng/othervm jdk.nashorn.api.javaaccess.NumberBoxingTest
*/
+@SuppressWarnings("javadoc")
public class NumberBoxingTest {
- private static ScriptEngine e = null;
- private static SharedObject o = null;
+ private static ScriptEngine e;
+ private static SharedObject o;
public static void main(final String[] args) {
TestNG.main(args);
@@ -77,10 +77,10 @@ public class NumberBoxingTest {
@Test
public void accessStaticFieldLongBoxing() throws ScriptException {
- e.eval("var ps_long = SharedObject.publicStaticLong;");
- assertEquals(SharedObject.publicStaticLong, e.get("ps_long"));
- e.eval("SharedObject.publicStaticLong = 120;");
- assertEquals(120, SharedObject.publicStaticLong);
+ e.eval("var ps_long = SharedObject.publicStaticLongBox;");
+ assertEquals(SharedObject.publicStaticLongBox, e.get("ps_long"));
+ e.eval("SharedObject.publicStaticLongBox = 120;");
+ assertEquals(120L, SharedObject.publicStaticLongBox.longValue());
}
@Test
@@ -138,7 +138,7 @@ public class NumberBoxingTest {
@Test
public void accessFieldByteBoxing() throws ScriptException {
e.eval("var p_byte = o.publicByteBox;");
- assertEquals(o.publicByteBox, e.get("p_byte"));
+ assertEqualsDouble(o.publicByteBox, "p_byte");
e.eval("o.publicByteBox = 16;");
assertEquals(Byte.valueOf((byte)16), o.publicByteBox);
}
@@ -146,7 +146,7 @@ public class NumberBoxingTest {
@Test
public void accessStaticFieldByteBoxing() throws ScriptException {
e.eval("var ps_byte = SharedObject.publicStaticByte;");
- assertEquals(SharedObject.publicStaticByte, e.get("ps_byte"));
+ assertEqualsDouble(SharedObject.publicStaticByte, "ps_byte");
e.eval("SharedObject.publicStaticByte = 16;");
assertEquals(16, SharedObject.publicStaticByte);
}
@@ -154,7 +154,7 @@ public class NumberBoxingTest {
@Test
public void accessFinalFieldByteBoxing() throws ScriptException {
e.eval("var pf_byte = o.publicFinalByteBox;");
- assertEquals(o.publicFinalByteBox, e.get("pf_byte"));
+ assertEqualsDouble(o.publicFinalByteBox, "pf_byte");
e.eval("o.publicFinalByteBox = 16;");
assertEquals(Byte.valueOf((byte)19), o.publicFinalByteBox);
}
@@ -162,7 +162,7 @@ public class NumberBoxingTest {
@Test
public void accessStaticFinalFieldByteBoxing() throws ScriptException {
e.eval("var psf_byte = SharedObject.publicStaticFinalByte;");
- assertEquals(SharedObject.publicStaticFinalByte, e.get("psf_byte"));
+ assertEqualsDouble(SharedObject.publicStaticFinalByte, "psf_byte");
e.eval("SharedObject.publicStaticFinalByte = 16;");
assertEquals(-70, SharedObject.publicStaticFinalByte);
}
@@ -172,15 +172,19 @@ public class NumberBoxingTest {
@Test
public void accessFieldShortBoxing() throws ScriptException {
e.eval("var p_short = o.publicShortBox;");
- assertEquals(o.publicShortBox, e.get("p_short"));
+ assertEqualsDouble(o.publicShortBox, "p_short");
e.eval("o.publicShortBox = 18;");
assertEquals(Short.valueOf((short)18), o.publicShortBox);
}
+ private static void assertEqualsDouble(final Number n, final String name) {
+ assertEquals(n.doubleValue(), ((Number)e.get(name)).doubleValue());
+ }
+
@Test
public void accessStaticFieldShortBoxing() throws ScriptException {
e.eval("var ps_short = SharedObject.publicStaticShort;");
- assertEquals(SharedObject.publicStaticShort, e.get("ps_short"));
+ assertEqualsDouble(SharedObject.publicStaticShort, "ps_short");
e.eval("SharedObject.publicStaticShort = 180;");
assertEquals(180, SharedObject.publicStaticShort);
}
@@ -188,7 +192,7 @@ public class NumberBoxingTest {
@Test
public void accessFinalFieldShortBoxing() throws ScriptException {
e.eval("var pf_short = o.publicFinalShortBox;");
- assertEquals(o.publicFinalShortBox, e.get("pf_short"));
+ assertEqualsDouble(o.publicFinalShortBox, "pf_short");
e.eval("o.publicFinalShortBox = 180;");
assertEquals(Short.valueOf((short)-26777), o.publicFinalShortBox);
}
@@ -196,7 +200,7 @@ public class NumberBoxingTest {
@Test
public void accessStaticFinalFieldShortBoxing() throws ScriptException {
e.eval("var psf_short = SharedObject.publicStaticFinalShort;");
- assertEquals(SharedObject.publicStaticFinalShort, e.get("psf_short"));
+ assertEqualsDouble(SharedObject.publicStaticFinalShort, "psf_short");
e.eval("SharedObject.publicStaticFinalShort = 180;");
assertEquals(8888, SharedObject.publicStaticFinalShort);
}
@@ -247,7 +251,7 @@ public class NumberBoxingTest {
@Test
public void accessFieldFloatBoxing() throws ScriptException {
e.eval("var p_float = o.publicFloatBox;");
- assertEquals(o.publicFloatBox, e.get("p_float"));
+ assertEqualsDouble(o.publicFloatBox, "p_float");
o.publicFloatBox = 0.0f / 0.0f;
assertEquals(true, e.eval("isNaN(o.publicFloatBox)"));
o.publicFloatBox = 1.0f / 0.0f;
@@ -267,7 +271,7 @@ public class NumberBoxingTest {
@Test
public void accessStaticFieldFloatBoxing() throws ScriptException {
e.eval("var ps_float = SharedObject.publicStaticFloat;");
- assertEquals(SharedObject.publicStaticFloat, e.get("ps_float"));
+ assertEqualsDouble(SharedObject.publicStaticFloat, "ps_float");
SharedObject.publicStaticFloat = 0.0f / 0.0f;
assertEquals(true, e.eval("isNaN(SharedObject.publicStaticFloat)"));
SharedObject.publicStaticFloat = 1.0f / 0.0f;
@@ -287,7 +291,7 @@ public class NumberBoxingTest {
@Test
public void accessFinalFloatBoxing() throws ScriptException {
e.eval("var pf_float = o.publicFinalFloatBox;");
- assertEquals(o.publicFinalFloatBox, e.get("pf_float"));
+ assertEqualsDouble(o.publicFinalFloatBox, "pf_float");
e.eval("o.publicFinalFloatBox = 20.0;");
assertEquals(1.372e4f, o.publicFinalFloatBox, 1e-10);
}
@@ -295,7 +299,7 @@ public class NumberBoxingTest {
@Test
public void accessStaticFinalFieldFloatBoxing() throws ScriptException {
e.eval("var psf_float = SharedObject.publicStaticFinalFloat;");
- assertEquals(SharedObject.publicStaticFinalFloat, e.get("psf_float"));
+ assertEqualsDouble(SharedObject.publicStaticFinalFloat, "psf_float");
e.eval("SharedObject.publicStaticFinalFloat = 20.0;");
assertEquals(0.72e8f, SharedObject.publicStaticFinalFloat, 1e-10);
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java
index 9c1fa114..00798a4e 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java
@@ -27,7 +27,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
-
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
@@ -41,6 +40,7 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.ObjectAccessTest
* @run testng/othervm jdk.nashorn.api.javaaccess.ObjectAccessTest
*/
+@SuppressWarnings("javadoc")
public class ObjectAccessTest {
private static ScriptEngine e = null;
diff --git a/test/src/jdk/nashorn/api/javaaccess/Person.java b/test/src/jdk/nashorn/api/javaaccess/Person.java
index 9012e636..32b1c9b7 100644
--- a/test/src/jdk/nashorn/api/javaaccess/Person.java
+++ b/test/src/jdk/nashorn/api/javaaccess/Person.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.javaaccess;
+@SuppressWarnings("javadoc")
public class Person {
public int id = 0;
diff --git a/test/src/jdk/nashorn/api/javaaccess/SharedObject.java b/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
index a7ef3ab3..93c93e19 100644
--- a/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
+++ b/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
@@ -29,6 +29,7 @@ import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
+@SuppressWarnings("javadoc")
public class SharedObject {
// Public fields
@@ -51,7 +52,7 @@ public class SharedObject {
public short publicShort = 32000;
public short[] publicShortArray = { 3240, 8900, -16789, 1, 12 };
public Short publicShortBox = Short.MIN_VALUE;
- public float publicFloat = 0.7e6f;
+ public float publicFloat = 0.7f;
public float[] publicFloatArray = { -32.01f, 89.3f, -1.3e8f, 3.1f };
public Float publicFloatBox = 1.377e4f;
public double publicDouble = 1.34e20;
@@ -162,7 +163,7 @@ public class SharedObject {
return engine;
}
- public void setEngine(ScriptEngine engine) {
+ public void setEngine(final ScriptEngine engine) {
this.engine = engine;
}
@@ -414,51 +415,51 @@ public class SharedObject {
t.start();
}
- public String overloadedMethodDoubleVSint(int arg) {
+ public String overloadedMethodDoubleVSint(final int arg) {
return "int";
}
- public String overloadedMethodDoubleVSint(double arg) {
+ public String overloadedMethodDoubleVSint(final double arg) {
return "double";
}
- public int overloadedMethod(int arg) {
+ public int overloadedMethod(final int arg) {
return arg*2;
}
- public int overloadedMethod(String arg) {
+ public int overloadedMethod(final String arg) {
return arg.length();
}
- public int overloadedMethod(boolean arg) {
+ public int overloadedMethod(final boolean arg) {
return (arg) ? 1 : 0;
}
- public int overloadedMethod(Person arg) {
+ public int overloadedMethod(final Person arg) {
return arg.id*2;
}
- public int firstLevelMethodInt(int arg) throws ScriptException, NoSuchMethodException {
+ public int firstLevelMethodInt(final int arg) throws ScriptException, NoSuchMethodException {
return (int) ((Invocable)engine).invokeFunction("secondLevelMethodInt", arg);
}
- public int thirdLevelMethodInt(int arg) {
+ public int thirdLevelMethodInt(final int arg) {
return arg*5;
}
- public int firstLevelMethodInteger(Integer arg) throws ScriptException, NoSuchMethodException {
+ public int firstLevelMethodInteger(final Integer arg) throws ScriptException, NoSuchMethodException {
return (int) ((Invocable)engine).invokeFunction("secondLevelMethodInteger", arg);
}
- public int thirdLevelMethodInteger(Integer arg) {
+ public int thirdLevelMethodInteger(final Integer arg) {
return arg*10;
}
- public Person firstLevelMethodObject(Person p) throws ScriptException, NoSuchMethodException {
+ public Person firstLevelMethodObject(final Person p) throws ScriptException, NoSuchMethodException {
return (Person) ((Invocable)engine).invokeFunction("secondLevelMethodObject", p);
}
- public Person thirdLevelMethodObject(Person p) {
+ public Person thirdLevelMethodObject(final Person p) {
p.id *= 10;
return p;
}
diff --git a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java
index 7b6a11f1..1e0a96aa 100644
--- a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java
@@ -27,7 +27,6 @@ package jdk.nashorn.api.javaaccess;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
-
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
@@ -41,6 +40,7 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.StringAccessTest
* @run testng/othervm jdk.nashorn.api.javaaccess.StringAccessTest
*/
+@SuppressWarnings("javadoc")
public class StringAccessTest {
private static ScriptEngine e = null;
diff --git a/test/src/jdk/nashorn/api/scripting/InvocableTest.java b/test/src/jdk/nashorn/api/scripting/InvocableTest.java
index a6722f57..4e44a296 100644
--- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java
+++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java
@@ -25,6 +25,8 @@
package jdk.nashorn.api.scripting;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
import java.util.Objects;
import java.util.function.Function;
import javax.script.Invocable;
@@ -34,16 +36,15 @@ import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
import org.testng.Assert;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
* Tests for javax.script.Invocable implementation of nashorn.
*/
+@SuppressWarnings("javadoc")
public class InvocableTest {
- private void log(String msg) {
+ private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -69,12 +70,12 @@ public class InvocableTest {
* evaluating script with different Context set.
*/
public void invokeMethodDifferentContextTest() {
- ScriptEngineManager m = new ScriptEngineManager();
- ScriptEngine e = m.getEngineByName("nashorn");
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
try {
// define an object with method on it
- Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
+ final Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
@@ -99,7 +100,7 @@ public class InvocableTest {
try {
final Object obj = e.eval("({})");
- final Object res = ((Invocable) e).invokeMethod(obj, null);
+ ((Invocable) e).invokeMethod(obj, null);
fail("should have thrown NPE");
} catch (final Exception exp) {
if (!(exp instanceof NullPointerException)) {
@@ -119,7 +120,7 @@ public class InvocableTest {
try {
final Object obj = e.eval("({})");
- final Object res = ((Invocable) e).invokeMethod(obj, "nonExistentMethod");
+ ((Invocable) e).invokeMethod(obj, "nonExistentMethod");
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
@@ -180,7 +181,7 @@ public class InvocableTest {
final ScriptEngine engine2 = m.getEngineByName("nashorn");
try {
- Object obj = engine1.eval("({ run: function() {} })");
+ final Object obj = engine1.eval("({ run: function() {} })");
// pass object from engine1 to engine2 as 'thiz' for invokeMethod
((Invocable) engine2).invokeMethod(obj, "run");
fail("should have thrown IllegalArgumentException");
@@ -211,7 +212,7 @@ public class InvocableTest {
// try interface on specific script object
try {
e.eval("var obj = { run: function() { print('run from obj'); } };");
- Object obj = e.get("obj");
+ final Object obj = e.get("obj");
final Runnable runnable = inv.getInterface(obj, Runnable.class);
runnable.run();
} catch (final Exception exp) {
@@ -307,17 +308,17 @@ public class InvocableTest {
* switching to use different ScriptContext.
*/
public void getInterfaceDifferentContext() {
- ScriptEngineManager m = new ScriptEngineManager();
- ScriptEngine e = m.getEngineByName("nashorn");
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
try {
- Object obj = e.eval("({ run: function() { } })");
+ final Object obj = e.eval("({ run: function() { } })");
// change script context
- ScriptContext ctxt = new SimpleScriptContext();
+ final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
e.setContext(ctxt);
- Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
+ final Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
r.run();
} catch (final Exception exp) {
exp.printStackTrace();
@@ -376,7 +377,7 @@ public class InvocableTest {
final ScriptEngine engine2 = m.getEngineByName("nashorn");
try {
- Object obj = engine1.eval("({ run: function() {} })");
+ final Object obj = engine1.eval("({ run: function() {} })");
// pass object from engine1 to engine2 as 'thiz' for getInterface
((Invocable) engine2).getInterface(obj, Runnable.class);
fail("should have thrown IllegalArgumentException");
@@ -397,7 +398,7 @@ public class InvocableTest {
final ScriptEngine e = m.getEngineByName("nashorn");
try {
- final Object res = ((Invocable) e).invokeFunction(null);
+ ((Invocable)e).invokeFunction(null);
fail("should have thrown NPE");
} catch (final Exception exp) {
if (!(exp instanceof NullPointerException)) {
@@ -417,7 +418,7 @@ public class InvocableTest {
final ScriptEngine e = m.getEngineByName("nashorn");
try {
- final Object res = ((Invocable) e).invokeFunction("NonExistentFunc");
+ ((Invocable)e).invokeFunction("NonExistentFunc");
fail("should have thrown NoSuchMethodException");
} catch (final Exception exp) {
if (!(exp instanceof NoSuchMethodException)) {
@@ -433,12 +434,12 @@ public class InvocableTest {
* Bindings.
*/
public void invokeFunctionDifferentContextTest() {
- ScriptEngineManager m = new ScriptEngineManager();
- ScriptEngine e = m.getEngineByName("nashorn");
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
try {
// define an object with method on it
- Object obj = e.eval("function hello() { return 'Hello World!'; }");
+ e.eval("function hello() { return 'Hello World!'; }");
final ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
// change engine's current context
@@ -525,14 +526,14 @@ public class InvocableTest {
}
@Test
- @SuppressWarnings("unchecked")
public void defaultMethodTest() throws ScriptException {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
final Invocable inv = (Invocable) e;
- Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
- Function<String, String> func = inv.getInterface(obj, Function.class);
+ final Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
+ @SuppressWarnings("unchecked")
+ final Function<String, String> func = inv.getInterface(obj, Function.class);
assertEquals(func.apply("hello"), "HELLO");
}
}
diff --git a/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java b/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java
index f72f8e61..218deff1 100644
--- a/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java
@@ -37,7 +37,7 @@ import org.testng.annotations.Test;
* @test
* @run testng jdk.nashorn.api.scripting.MultipleEngineTest
*/
-
+@SuppressWarnings("javadoc")
public class MultipleEngineTest {
@Test
public void createAndUseManyEngine() throws ScriptException {
diff --git a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
index a574e6f6..b277bdef 100644
--- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
+++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
@@ -25,6 +25,10 @@
package jdk.nashorn.api.scripting;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.HashMap;
@@ -32,11 +36,6 @@ import java.util.LinkedHashMap;
import java.util.Set;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
@@ -45,6 +44,7 @@ import org.testng.annotations.Test;
* JDK-8024615: Refactor ScriptObjectMirror and JSObject to support external
* JSObject implementations.
*/
+@SuppressWarnings("javadoc")
public class PluggableJSObjectTest {
public static class MapWrapperObject extends AbstractJSObject {
private final HashMap<String, Object> map = new LinkedHashMap<>();
@@ -54,22 +54,22 @@ public class PluggableJSObjectTest {
}
@Override
- public Object getMember(String name) {
+ public Object getMember(final String name) {
return map.get(name);
}
@Override
- public void setMember(String name, Object value) {
+ public void setMember(final String name, final Object value) {
map.put(name, value);
}
@Override
- public boolean hasMember(String name) {
+ public boolean hasMember(final String name) {
return map.containsKey(name);
}
@Override
- public void removeMember(String name) {
+ public void removeMember(final String name) {
map.remove(name);
}
@@ -112,7 +112,7 @@ public class PluggableJSObjectTest {
public static class BufferObject extends AbstractJSObject {
private final IntBuffer buf;
- public BufferObject(int size) {
+ public BufferObject(final int size) {
buf = IntBuffer.allocate(size);
}
@@ -121,22 +121,22 @@ public class PluggableJSObjectTest {
}
@Override
- public Object getMember(String name) {
+ public Object getMember(final String name) {
return name.equals("length")? buf.capacity() : null;
}
@Override
- public boolean hasSlot(int i) {
+ public boolean hasSlot(final int i) {
return i > -1 && i < buf.capacity();
}
@Override
- public Object getSlot(int i) {
+ public Object getSlot(final int i) {
return buf.get(i);
}
@Override
- public void setSlot(int i, Object value) {
+ public void setSlot(final int i, final Object value) {
buf.put(i, ((Number)value).intValue());
}
@@ -172,9 +172,9 @@ public class PluggableJSObjectTest {
public static class Adder extends AbstractJSObject {
@Override
- public Object call(Object thiz, Object... args) {
+ public Object call(final Object thiz, final Object... args) {
double res = 0.0;
- for (Object arg : args) {
+ for (final Object arg : args) {
res += ((Number)arg).doubleValue();
}
return res;
@@ -203,8 +203,9 @@ public class PluggableJSObjectTest {
}
public static class Factory extends AbstractJSObject {
+ @SuppressWarnings("unused")
@Override
- public Object newObject(Object... args) {
+ public Object newObject(final Object... args) {
return new HashMap<Object, Object>();
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScopeTest.java b/test/src/jdk/nashorn/api/scripting/ScopeTest.java
index e2aec242..4e1dfe78 100644
--- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java
@@ -24,6 +24,10 @@
*/
package jdk.nashorn.api.scripting;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -32,22 +36,19 @@ import javax.script.ScriptException;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
import org.testng.Assert;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
* Tests for jsr223 Bindings "scope" (engine, global scopes)
*/
+@SuppressWarnings("javadoc")
public class ScopeTest {
@Test
public void createBindingsTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
- Bindings b = e.createBindings();
+ final Bindings b = e.createBindings();
b.put("foo", 42.0);
Object res = null;
try {
@@ -64,7 +65,7 @@ public class ScopeTest {
public void engineScopeTest() {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
- Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
+ final Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
// check few ECMA standard built-in global properties
assertNotNull(engineScope.get("Object"));
@@ -112,8 +113,8 @@ public class ScopeTest {
newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
try {
- Object obj1 = e.eval("Object");
- Object obj2 = e.eval("Object", newCtxt);
+ final Object obj1 = e.eval("Object");
+ final Object obj2 = e.eval("Object", newCtxt);
Assert.assertNotEquals(obj1, obj2);
Assert.assertNotNull(obj1);
Assert.assertNotNull(obj2);
@@ -138,10 +139,12 @@ public class ScopeTest {
e.eval("y = new Object()");
e.eval("y = new Object()", origCtxt);
- Object y1 = origCtxt.getAttribute("y");
- Object y2 = newCtxt.getAttribute("y");
+ final Object y1 = origCtxt.getAttribute("y");
+ final Object y2 = newCtxt.getAttribute("y");
Assert.assertNotEquals(y1, y2);
- Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
+ final Object yeval1 = e.eval("y");
+ final Object yeval2 = e.eval("y", origCtxt);
+ Assert.assertNotEquals(yeval1, yeval2);
Assert.assertEquals("[object Object]", y1.toString());
Assert.assertEquals("[object Object]", y2.toString());
} catch (final ScriptException se) {
@@ -159,7 +162,7 @@ public class ScopeTest {
final ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
// we are using a new bindings - so it should have 'func' defined
- Object value = e.eval("typeof func", newContext);
+ final Object value = e.eval("typeof func", newContext);
assertTrue(value.equals("undefined"));
}
@@ -210,7 +213,7 @@ public class ScopeTest {
assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
// check new global instance created has engine.js definitions
- Bindings b = e.createBindings();
+ final Bindings b = e.createBindings();
value = b.get("__noSuchProperty__");
assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
value = b.get("print");
@@ -231,7 +234,7 @@ public class ScopeTest {
assertTrue(e.eval("x", ctx).equals("hello"));
// try some arbitray Bindings for ENGINE_SCOPE
- Bindings sb = new SimpleBindings();
+ final Bindings sb = new SimpleBindings();
ctx.setBindings(sb, ScriptContext.ENGINE_SCOPE);
// GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
@@ -305,7 +308,7 @@ public class ScopeTest {
t1.join();
t2.join();
- Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
+ final Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
assertEquals(obj3, "newer context");
final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
@@ -342,7 +345,7 @@ public class ScopeTest {
for (int i = 0; i < 1000; i++) {
assertEquals(e.eval(sharedScript, origContext), (double)i);
}
- } catch (ScriptException se) {
+ } catch (final ScriptException se) {
fail(se.toString());
}
}
@@ -354,7 +357,7 @@ public class ScopeTest {
for (int i = 2; i < 1000; i++) {
assertEquals(e.eval(sharedScript, newCtxt), (double)i);
}
- } catch (ScriptException se) {
+ } catch (final ScriptException se) {
fail(se.toString());
}
}
@@ -377,8 +380,8 @@ public class ScopeTest {
final ScriptContext newCtxt = new SimpleScriptContext();
newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
- Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
- Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
+ final Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
+ final Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
assertEquals(obj1, "original context");
assertEquals(obj2, "new context");
final String sharedScript = "''.foo";
@@ -390,7 +393,7 @@ public class ScopeTest {
t1.join();
t2.join();
- Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+ final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
assertEquals(obj3, "newer context");
final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
@@ -404,6 +407,75 @@ public class ScopeTest {
Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
}
+
+ /**
+ * Test multi-threaded access to prototype user accessor properties for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedAccessorTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'original context' })", origContext);
+ e.eval("Object.defineProperty(Object.prototype, 'foo', { get: function() 'new context', configurable: true })", newCtxt);
+ final String sharedScript = "({}).foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ final Object obj3 = e.eval("delete Object.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+ }
+
+ /**
+ * Test multi-threaded access to primitive prototype user accessor properties for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedPrimitiveAccessorTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'original context' })", origContext);
+ e.eval("Object.defineProperty(String.prototype, 'foo', { get: function() 'new context' })", newCtxt);
+ final String sharedScript = "''.foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+ }
+
/**
* Test multi-threaded scope function invocation for shared script classes with multiple globals.
*/
@@ -510,6 +582,60 @@ public class ScopeTest {
assertEquals(e.eval("x", newCtxt), 2);
}
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void contextOverwriteTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = new SimpleBindings();
+ b.put("context", "hello");
+ b.put("foo", 32);
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ e.setContext(newCtxt);
+ assertEquals(e.eval("context"), "hello");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void contextOverwriteInScriptTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ e.put("foo", 32);
+
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ assertEquals(e.eval("context = 'bar'"), "bar");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void engineOverwriteTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = new SimpleBindings();
+ b.put("engine", "hello");
+ b.put("foo", 32);
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ e.setContext(newCtxt);
+ assertEquals(e.eval("engine"), "hello");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
+ // @bug 8058422: Users should be able to overwrite "context" and "engine" variables
+ @Test
+ public static void engineOverwriteInScriptTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ e.put("foo", 32);
+
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ assertEquals(e.eval("engine = 'bar'"), "bar");
+ assertEquals(((Number)e.eval("foo")).intValue(), 32);
+ }
+
// @bug 8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
@Test
public static void testMegamorphicGetInGlobal() throws Exception {
@@ -529,6 +655,8 @@ public class ScopeTest {
/**
* Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals.
+ * @throws ScriptException
+ * @throws InterruptedException
*/
@Test
public static void testSlowScope() throws ScriptException, InterruptedException {
@@ -572,7 +700,7 @@ public class ScopeTest {
for (int i = 0; i < iterations; i++) {
assertEquals(engine.eval(source, context), expected);
}
- } catch (ScriptException se) {
+ } catch (final ScriptException se) {
throw new RuntimeException(se);
}
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
index 6d0d40f6..06b89e83 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
@@ -26,12 +26,9 @@
package jdk.nashorn.api.scripting;
import static org.testng.Assert.fail;
-
-import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
-import java.util.Objects;
-import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
@@ -40,9 +37,10 @@ import org.testng.annotations.Test;
/**
* jsr223 tests for security access checks.
*/
+@SuppressWarnings("javadoc")
public class ScriptEngineSecurityTest {
- private void log(String msg) {
+ private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -168,55 +166,20 @@ public class ScriptEngineSecurityTest {
}
}
- @Test
- /**
- * Check that script can't implement sensitive package interfaces.
- */
- public void checkSensitiveInterfaceImplTest() throws ScriptException {
- if (System.getSecurityManager() == null) {
- // pass vacuously
- return;
- }
-
- final ScriptEngineManager m = new ScriptEngineManager();
- final ScriptEngine e = m.getEngineByName("nashorn");
- final Object[] holder = new Object[1];
- e.put("holder", holder);
- // put an empty script object into array
- e.eval("holder[0] = {}");
- // holder[0] is an object of some subclass of ScriptObject
- Class ScriptObjectClass = holder[0].getClass().getSuperclass();
- Class PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
- // implementation methods for PropertyAccess class
- e.eval("function set() {}; function get() {}; function getInt(){} " +
- "function getDouble(){}; function getLong() {}; " +
- "this.delete = function () {}; function has() {}; " +
- "function hasOwnProperty() {}");
-
- // get implementation of a restricted package interface
- try {
- log(Objects.toString(((Invocable)e).getInterface((Class<?>)PropertyAccessClass)));
- fail("should have thrown SecurityException");
- } catch (final Exception exp) {
- if (! (exp instanceof SecurityException)) {
- fail("SecurityException expected, got " + exp);
- }
- }
- }
-
// @bug 8032948: Nashorn linkages awry
+ @SuppressWarnings("serial")
public static class FakeProxy extends Proxy {
- public FakeProxy(InvocationHandler ih) {
+ public FakeProxy(final InvocationHandler ih) {
super(ih);
}
- public static Class<?> makeProxyClass(ClassLoader cl, Class<?>... ifaces) {
+ public static Class<?> makeProxyClass(final ClassLoader cl, final Class<?>... ifaces) {
return Proxy.getProxyClass(cl, ifaces);
}
}
@Test
- public void fakeProxySubclassAccessCheckTest() throws ScriptException {
+ public void fakeProxySubclassAccessCheckTest() {
if (System.getSecurityManager() == null) {
// pass vacuously
return;
@@ -229,11 +192,11 @@ public class ScriptEngineSecurityTest {
e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
e.put("intfs", new Class[] { Runnable.class });
- String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);";
+ final String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);";
// Should not be able to call static methods of Proxy via fake subclass
try {
- Class c = (Class)e.eval(getClass);
+ e.eval(getClass);
fail("should have thrown SecurityException");
} catch (final Exception exp) {
if (! (exp instanceof SecurityException)) {
@@ -243,7 +206,7 @@ public class ScriptEngineSecurityTest {
}
@Test
- public void fakeProxySubclassAccessCheckTest2() throws ScriptException {
+ public void fakeProxySubclassAccessCheckTest2() {
if (System.getSecurityManager() == null) {
// pass vacuously
return;
@@ -256,11 +219,11 @@ public class ScriptEngineSecurityTest {
e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
e.put("intfs", new Class[] { Runnable.class });
- String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);";
+ final String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);";
// Should not be able to call static methods of Proxy via fake subclass
try {
- Class c = (Class)e.eval(getClass);
+ e.eval(getClass);
fail("should have thrown SecurityException");
} catch (final Exception exp) {
if (! (exp instanceof SecurityException)) {
@@ -270,7 +233,12 @@ public class ScriptEngineSecurityTest {
}
@Test
- public static void proxyStaticAccessCheckTest() throws ScriptException {
+ public static void proxyStaticAccessCheckTest() {
+ if (System.getSecurityManager() == null) {
+ // pass vacuously
+ return;
+ }
+
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
final Runnable r = (Runnable)Proxy.newProxyInstance(
@@ -278,7 +246,7 @@ public class ScriptEngineSecurityTest {
new Class[] { Runnable.class },
new InvocationHandler() {
@Override
- public Object invoke(Object p, Method m, Object[] a) {
+ public Object invoke(final Object p, final Method mtd, final Object[] a) {
return null;
}
});
@@ -297,4 +265,47 @@ public class ScriptEngineSecurityTest {
}
}
}
+
+
+ @Test
+ public void nashornConfigSecurityTest() {
+ if (System.getSecurityManager() == null) {
+ // pass vacuously
+ return;
+ }
+
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine(new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String name) {
+ return true;
+ }
+ });
+ fail("SecurityException should have been thrown");
+ } catch (final SecurityException e) {
+ //empty
+ }
+ }
+
+ @Test
+ public void nashornConfigSecurityTest2() {
+ if (System.getSecurityManager() == null) {
+ // pass vacuously
+ return;
+ }
+
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine(new String[0], null, new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String name) {
+ return true;
+ }
+ });
+ fail("SecurityException should have been thrown");
+ } catch (final SecurityException e) {
+ //empty
+ }
+ }
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index 52199145..a066d6b3 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -29,8 +29,6 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-
-import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationHandler;
@@ -39,6 +37,7 @@ import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import javax.script.Compilable;
import javax.script.CompiledScript;
+import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
@@ -54,9 +53,10 @@ import org.testng.annotations.Test;
* @build jdk.nashorn.api.scripting.Window jdk.nashorn.api.scripting.WindowEventHandler jdk.nashorn.api.scripting.VariableArityTestInterface jdk.nashorn.api.scripting.ScriptEngineTest
* @run testng/othervm jdk.nashorn.api.scripting.ScriptEngineTest
*/
+@SuppressWarnings("javadoc")
public class ScriptEngineTest {
- private void log(String msg) {
+ private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -65,11 +65,11 @@ public class ScriptEngineTest {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
- String[] args = new String[] { "hello", "world" };
+ final String[] args = new String[] { "hello", "world" };
try {
e.put("arguments", args);
- Object arg0 = e.eval("arguments[0]");
- Object arg1 = e.eval("arguments[1]");
+ final Object arg0 = e.eval("arguments[0]");
+ final Object arg1 = e.eval("arguments[1]");
assertEquals(args[0], arg0);
assertEquals(args[1], arg1);
} catch (final Exception exp) {
@@ -83,12 +83,12 @@ public class ScriptEngineTest {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
- String[] args = new String[] { "hello", "world" };
+ final String[] args = new String[] { "hello", "world" };
try {
e.put("arguments", args);
- Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
+ final Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
" with(imports) { arguments[0] }");
- Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
+ final Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
" with(imports) { arguments[1] }");
assertEquals(args[0], arg0);
assertEquals(args[1], arg1);
@@ -129,22 +129,24 @@ public class ScriptEngineTest {
assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
boolean seenJS = false;
- for (String ext : fac.getExtensions()) {
+ for (final String ext : fac.getExtensions()) {
if (ext.equals("js")) {
seenJS = true;
}
}
assertEquals(seenJS, true);
- String str = fac.getMethodCallSyntax("obj", "foo", "x");
+ final String str = fac.getMethodCallSyntax("obj", "foo", "x");
assertEquals(str, "obj.foo(x)");
boolean seenNashorn = false, seenJavaScript = false, seenECMAScript = false;
- for (String name : fac.getNames()) {
+ for (final String name : fac.getNames()) {
switch (name) {
case "nashorn": seenNashorn = true; break;
case "javascript": seenJavaScript = true; break;
case "ECMAScript": seenECMAScript = true; break;
+ default:
+ break;
}
}
@@ -153,12 +155,14 @@ public class ScriptEngineTest {
assertTrue(seenECMAScript);
boolean seenAppJS = false, seenAppECMA = false, seenTextJS = false, seenTextECMA = false;
- for (String mime : fac.getMimeTypes()) {
+ for (final String mime : fac.getMimeTypes()) {
switch (mime) {
case "application/javascript": seenAppJS = true; break;
case "application/ecmascript": seenAppECMA = true; break;
case "text/javascript": seenTextJS = true; break;
case "text/ecmascript": seenTextECMA = true; break;
+ default:
+ break;
}
}
@@ -548,7 +552,7 @@ public class ScriptEngineTest {
new Class[] { Runnable.class },
new InvocationHandler() {
@Override
- public Object invoke(Object p, Method m, Object[] a) {
+ public Object invoke(final Object p, final Method mtd, final Object[] a) {
reached[0] = true;
return null;
}
@@ -594,9 +598,79 @@ public class ScriptEngineTest {
}
}
+ // @bug 8046013: TypeError: Cannot apply "with" to non script object
+ @Test
+ public void withOnMirrorTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ final Object obj = e.eval("({ foo: 'hello'})");
+ final Object[] arr = new Object[1];
+ arr[0] = obj;
+ e.put("arr", arr);
+ final Object res = e.eval("var res; with(arr[0]) { res = foo; }; res");
+ assertEquals(res, "hello");
+ }
+
+ // @bug 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
+ @Test
+ public void check__DIR__Test() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ e.eval("__DIR__");
+ }
+
+ // @bug 8050432:javax.script.filename variable should not be enumerable
+ // with nashorn engine's ENGINE_SCOPE bindings
+ @Test
+ public void enumerableGlobalsTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ e.put(ScriptEngine.FILENAME, "test");
+ final Object enumerable = e.eval(
+ "Object.getOwnPropertyDescriptor(this, " +
+ " 'javax.script.filename').enumerable");
+ assertEquals(enumerable, Boolean.FALSE);
+ }
+
+ public static class Context {
+ private Object myobj;
+
+ public void set(final Object o) {
+ myobj = o;
+ }
+
+ public Object get() {
+ return myobj;
+ }
+ }
+
+ // @bug 8050977: Java8 Javascript Nashorn exception:
+ // no current Global instance for nashorn
+ @Test
+ public void currentGlobalMissingTest() throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine e = manager.getEngineByName("nashorn");
+
+ final Context ctx = new Context();
+ e.put("ctx", ctx);
+ e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }");
+ e.eval("ctx.set(obj)");
+ final Invocable inv = (Invocable)e;
+ assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello"));
+ // try object literal
+ e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })");
+ assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO"));
+ // try array literal
+ e.eval("var arr = [ 'hello', 'world' ]");
+ e.eval("ctx.set(arr)");
+ assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
+ }
+
private static void checkProperty(final ScriptEngine e, final String name)
throws ScriptException {
- String value = System.getProperty(name);
+ final String value = System.getProperty(name);
e.put("name", name);
assertEquals(value, e.eval("java.lang.System.getProperty(name)"));
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
index 30eaefca..ce3b421c 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
@@ -25,24 +25,28 @@
package jdk.nashorn.api.scripting;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import javax.script.Bindings;
+import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
* Tests to check jdk.nashorn.api.scripting.ScriptObjectMirror API.
*/
+@SuppressWarnings("javadoc")
public class ScriptObjectMirrorTest {
@SuppressWarnings("unchecked")
@@ -133,7 +137,7 @@ public class ScriptObjectMirrorTest {
final ScriptEngine e = m.getEngineByName("nashorn");
try {
e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
- ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj");
+ final ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj");
// try basic get on existing properties
if (!obj.getMember("bar").equals("hello")) {
@@ -190,7 +194,7 @@ public class ScriptObjectMirrorTest {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
try {
- Object obj = e.eval("new TypeError('wrong type')");
+ final Object obj = e.eval("new TypeError('wrong type')");
assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
} catch (final Throwable t) {
t.printStackTrace();
@@ -198,7 +202,7 @@ public class ScriptObjectMirrorTest {
}
try {
- Object obj = e.eval("function func() { print('hello'); }");
+ final Object obj = e.eval("function func() { print('hello'); }");
assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
} catch (final Throwable t) {
t.printStackTrace();
@@ -305,4 +309,79 @@ public class ScriptObjectMirrorTest {
// getMember("obj.foo") - thereby getting null instead of undefined
assertEquals("undefined", engine.eval(TEST_SCRIPT, newGlobal));
}
+
+ public interface MirrorCheckExample {
+ Object test1(Object arg);
+ Object test2(Object arg);
+ boolean compare(Object o1, Object o2);
+ }
+
+ // @bug 8053910: ScriptObjectMirror causing havoc with Invocation interface
+ @Test
+ public void checkMirrorToObject() throws Exception {
+ final ScriptEngineManager engineManager = new ScriptEngineManager();
+ final ScriptEngine engine = engineManager.getEngineByName("nashorn");
+ final Invocable invocable = (Invocable)engine;
+
+ engine.eval("function test1(arg) { return { arg: arg }; }");
+ engine.eval("function test2(arg) { return arg; }");
+ engine.eval("function compare(arg1, arg2) { return arg1 == arg2; }");
+
+ final Map<String, Object> map = new HashMap<>();
+ map.put("option", true);
+
+ final MirrorCheckExample example = invocable.getInterface(MirrorCheckExample.class);
+
+ final Object value1 = invocable.invokeFunction("test1", map);
+ final Object value2 = example.test1(map);
+ final Object value3 = invocable.invokeFunction("test2", value2);
+ final Object value4 = example.test2(value2);
+
+ // check that Object type argument receives a ScriptObjectMirror
+ // when ScriptObject is passed
+ assertEquals(ScriptObjectMirror.class, value1.getClass());
+ assertEquals(ScriptObjectMirror.class, value2.getClass());
+ assertEquals(ScriptObjectMirror.class, value3.getClass());
+ assertEquals(ScriptObjectMirror.class, value4.getClass());
+ assertTrue((boolean)invocable.invokeFunction("compare", value1, value1));
+ assertTrue(example.compare(value1, value1));
+ assertTrue((boolean)invocable.invokeFunction("compare", value3, value4));
+ assertTrue(example.compare(value3, value4));
+ }
+
+ // @bug 8053910: ScriptObjectMirror causing havoc with Invocation interface
+ @Test
+ public void mirrorUnwrapInterfaceMethod() throws Exception {
+ final ScriptEngineManager engineManager = new ScriptEngineManager();
+ final ScriptEngine engine = engineManager.getEngineByName("nashorn");
+ final Invocable invocable = (Invocable)engine;
+ engine.eval("function apply(obj) { " +
+ " return obj instanceof Packages.jdk.nashorn.api.scripting.ScriptObjectMirror; " +
+ "}");
+ @SuppressWarnings("unchecked")
+ final Function<Object,Object> func = invocable.getInterface(Function.class);
+ assertFalse((boolean)func.apply(engine.eval("({ x: 2 })")));
+ }
+
+ // @bug 8055687: Wrong "this" passed to JSObject.eval call
+ @Test
+ public void checkThisForJSObjectEval() throws Exception {
+ final ScriptEngineManager engineManager = new ScriptEngineManager();
+ final ScriptEngine e = engineManager.getEngineByName("nashorn");
+ final JSObject jsobj = (JSObject)e.eval("({foo: 23, bar: 'hello' })");
+ assertEquals(((Number)jsobj.eval("this.foo")).intValue(), 23);
+ assertEquals(jsobj.eval("this.bar"), "hello");
+ assertEquals(jsobj.eval("String(this)"), "[object Object]");
+ final Object global = e.eval("this");
+ assertFalse(global.equals(jsobj.eval("this")));
+ }
+
+ @Test
+ public void topLevelAnonFuncStatement() throws Exception {
+ final ScriptEngineManager engineManager = new ScriptEngineManager();
+ final ScriptEngine e = engineManager.getEngineByName("nashorn");
+ final JSObject func = (JSObject)e.eval("function(x) { return x + ' world' }");
+ assertTrue(func.isFunction());
+ assertEquals(func.call(e.eval("this"), "hello"), "hello world");
+ }
}
diff --git a/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java b/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java
index d3904522..8ce5e490 100644
--- a/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java
+++ b/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.scripting;
+@SuppressWarnings("javadoc")
public interface VariableArityTestInterface {
public String test1(int i, String... strings);
public String test2(int i, String... strings);
diff --git a/test/src/jdk/nashorn/api/scripting/Window.java b/test/src/jdk/nashorn/api/scripting/Window.java
index 510c5dae..7a7476f5 100644
--- a/test/src/jdk/nashorn/api/scripting/Window.java
+++ b/test/src/jdk/nashorn/api/scripting/Window.java
@@ -28,6 +28,7 @@ package jdk.nashorn.api.scripting;
import java.util.Map;
import javax.script.Bindings;
+@SuppressWarnings("javadoc")
public class Window {
private String location = "http://localhost:8080/window";
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
index 88892994..dfcad5a9 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
@@ -25,8 +25,7 @@
package jdk.nashorn.api.scripting;
+@SuppressWarnings("javadoc")
public interface WindowEventHandler {
-
public boolean loaded();
-
}
diff --git a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
index 1ebb97a2..61d896b6 100644
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
+++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
@@ -25,9 +25,8 @@
package jdk.nashorn.internal.codegen;
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
import static jdk.nashorn.internal.runtime.Source.readFully;
-
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -45,6 +44,7 @@ import org.testng.annotations.Test;
/**
* Tests to check Nashorn JS compiler - just compiler and not execution of scripts.
*/
+@SuppressWarnings("javadoc")
public class CompilerTest {
private static final boolean VERBOSE = Boolean.valueOf(System.getProperty("compilertest.verbose"));
private static final boolean TEST262 = Boolean.valueOf(System.getProperty("compilertest.test262"));
@@ -56,7 +56,7 @@ public class CompilerTest {
public boolean exclude(File file, String content);
}
- private void log(String msg) {
+ private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -72,6 +72,7 @@ public class CompilerTest {
options.set("print.parse", true);
options.set("scripting", true);
options.set("const.as.var", true);
+ options.set("verify.code", true);
final ErrorManager errors = new ErrorManager() {
@Override
@@ -98,11 +99,16 @@ public class CompilerTest {
compileTestSet(new File(TEST262_SUITE_DIR), new TestFilter() {
@Override
public boolean exclude(final File file, final String content) {
- return content.indexOf("@negative") != -1;
+ return content != null && content.contains("@negative");
}
});
}
- compileTestSet(new File(TEST_BASIC_DIR), null);
+ compileTestSet(new File(TEST_BASIC_DIR), new TestFilter() {
+ @Override
+ public boolean exclude(final File file, final String content) {
+ return file.getName().equals("es6");
+ }
+ });
compileTestSet(new File(TEST_NODE_DIR, "node"), null);
compileTestSet(new File(TEST_NODE_DIR, "src"), null);
}
@@ -136,6 +142,9 @@ public class CompilerTest {
private int skipped;
private void compileJSDirectory(final File dir, final TestFilter filter) {
+ if (filter != null && filter.exclude(dir, null)) {
+ return;
+ }
for (final File f : dir.listFiles()) {
if (f.isDirectory()) {
compileJSDirectory(f, filter);
diff --git a/test/src/jdk/nashorn/internal/parser/ParserTest.java b/test/src/jdk/nashorn/internal/parser/ParserTest.java
index 8a68bb11..110f6237 100644
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java
+++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java
@@ -25,9 +25,8 @@
package jdk.nashorn.internal.parser;
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
import static jdk.nashorn.internal.runtime.Source.readFully;
-
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.File;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
@@ -41,6 +40,7 @@ import org.testng.annotations.Test;
/**
* Run tests to check Nashorn's parser.
*/
+@SuppressWarnings("javadoc")
public class ParserTest {
private static final boolean VERBOSE = Boolean.valueOf(System.getProperty("parsertest.verbose"));
private static final boolean TEST262 = Boolean.valueOf(System.getProperty("parsertest.test262"));
@@ -53,7 +53,7 @@ public class ParserTest {
public boolean exclude(File file, String content);
}
- private void log(String msg) {
+ private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -67,7 +67,7 @@ public class ParserTest {
options.set("scripting", true);
options.set("const.as.var", true);
- ErrorManager errors = new ErrorManager();
+ final ErrorManager errors = new ErrorManager();
this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
}
@@ -82,11 +82,16 @@ public class ParserTest {
parseTestSet(TEST262_SUITE_DIR, new TestFilter() {
@Override
public boolean exclude(final File file, final String content) {
- return content.indexOf("@negative") != -1;
+ return content != null && content.contains("@negative");
}
});
}
- parseTestSet(TEST_BASIC_DIR, null);
+ parseTestSet(TEST_BASIC_DIR, new TestFilter() {
+ @Override
+ public boolean exclude(final File file, final String content) {
+ return file.getName().equals("es6");
+ }
+ });
}
private void parseTestSet(final String testSet, final TestFilter filter) {
@@ -120,6 +125,9 @@ public class ParserTest {
private int skipped;
private void parseJSDirectory(final File dir, final TestFilter filter) {
+ if (filter != null && filter.exclude(dir, null)) {
+ return;
+ }
for (final File f : dir.listFiles()) {
if (f.isDirectory()) {
parseJSDirectory(f, filter);
@@ -157,8 +165,8 @@ public class ParserTest {
}
};
errors.setLimit(0);
- final Source source = sourceFor(file.getAbsolutePath(), buffer);
- new Parser(context.getEnv(), source, errors).parse();
+ final Source source = sourceFor(file.getAbsolutePath(), buffer);
+ new Parser(context.getEnv(), source, errors, context.getEnv()._strict, null).parse();
if (errors.getNumberOfErrors() > 0) {
log("Parse failed: " + file.getAbsolutePath());
failed++;
@@ -166,6 +174,7 @@ public class ParserTest {
passed++;
}
} catch (final Throwable exp) {
+ exp.printStackTrace();
log("Parse failed: " + file.getAbsolutePath() + " : " + exp);
if (VERBOSE) {
exp.printStackTrace(System.out);
diff --git a/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java b/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java
index a3f4caa1..ccc3930e 100644
--- a/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java
+++ b/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java
@@ -43,6 +43,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+@SuppressWarnings("javadoc")
public class AuroraWrapper {
public static String fileName = "report.xml";
diff --git a/test/src/jdk/nashorn/internal/performance/OctaneTest.java b/test/src/jdk/nashorn/internal/performance/OctaneTest.java
index 7e402c65..102ffc1a 100644
--- a/test/src/jdk/nashorn/internal/performance/OctaneTest.java
+++ b/test/src/jdk/nashorn/internal/performance/OctaneTest.java
@@ -40,6 +40,7 @@ import java.text.NumberFormat;
import java.util.List;
import org.testng.annotations.Test;
+@SuppressWarnings("javadoc")
public class OctaneTest {
@Test
@@ -72,7 +73,7 @@ public class OctaneTest {
genericTest("GBEMU");
}
- /* @Test
+/* @Test
public void mandreelTest() {
genericTest("Mandreel");
}*/
@@ -107,11 +108,21 @@ public class OctaneTest {
genericTest("Splay");
}
+ @Test
+/* public void typeScriptTest() {
+ genericTest("TypeScript");
+ }
+
+ @Test
+ public void zlibTest() {
+ genericTest("zlib");
+ }/*/
+
public void genericTest(final String benchmark) {
try {
final String mainScript = "test/script/basic/run-octane.js";
- final String benchmarkScript = "test/script/external/octane/benchmarks/"+benchmark.toLowerCase() + ".js";
- String[] args = {
+ final String benchmarkScript = "test/script/external/octane/benchmarks/" + benchmark.toLowerCase() + ".js";
+ final String[] args = {
"--",
benchmarkScript,
"--verbose"
@@ -136,16 +147,17 @@ public class OctaneTest {
}
}
- public Double genericNashornTest(final String benchmark, final String testPath, String[] args) throws Throwable {
+ public Double genericNashornTest(final String benchmark, final String testPath, final String[] args) throws Throwable {
try {
final PerformanceWrapper wrapper = new PerformanceWrapper();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
- java.io.File test=new java.io.File(testPath);
- File absoluteFile=test.getAbsoluteFile();
+ final java.io.File test=new java.io.File(testPath);
+ final File absoluteFile=test.getAbsoluteFile();
@SuppressWarnings("deprecation")
+ final
URL testURL=absoluteFile.toURL();
wrapper.runExecuteOnlyTest(testPath, 0, 0, testURL.toString(), ps, System.err, args);
@@ -153,7 +165,7 @@ public class OctaneTest {
final byte[] output = baos.toByteArray();
final List<String> result = outputToStrings(output);
- Double _result = filterBenchmark(result, benchmark);
+ final Double _result = filterBenchmark(result, benchmark);
return _result;
} catch (final Throwable e) {
@@ -265,7 +277,7 @@ public class OctaneTest {
if (v8 != null && rhino != 0) {
nashornToV8 = nashorn.doubleValue() / v8.doubleValue();
}
- String normalizedBenchmark=benchmark.replace("-", "");
+ final String normalizedBenchmark=benchmark.replace("-", "");
System.out.println("benchmark-" + normalizedBenchmark + "-nashorn=" + nashorn);
AuroraWrapper.addResults(AuroraWrapper.createOrOpenDocument(), "benchmark-" + normalizedBenchmark + "-nashorn", nashorn.toString());
diff --git a/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java b/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
index ce969210..cd3d322b 100644
--- a/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
+++ b/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
@@ -36,10 +36,7 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
-/**
- *
- * @author Pavel Stepanov
- */
+@SuppressWarnings("javadoc")
public class PerformanceWrapper extends jdk.nashorn.tools.Shell {
int _numberOfIterations;
@@ -72,8 +69,8 @@ public class PerformanceWrapper extends jdk.nashorn.tools.Shell {
}
- protected void runExecuteOnlyTest(final String name, final int numberOfIterations, final int runsPerIteration, final String testURL, final OutputStream out, final OutputStream err, String[] newargs) throws Throwable {
- String[] args=new String[newargs.length+1];
+ protected void runExecuteOnlyTest(final String name, final int numberOfIterations, final int runsPerIteration, final String testURL, final OutputStream out, final OutputStream err, final String[] newargs) throws Throwable {
+ final String[] args=new String[newargs.length+1];
System.arraycopy(newargs, 0, args, 1, newargs.length);
args[0]=name;
diff --git a/test/src/jdk/nashorn/internal/performance/SplayTest.java b/test/src/jdk/nashorn/internal/performance/SplayTest.java
index e937a0f4..d80b1aa2 100644
--- a/test/src/jdk/nashorn/internal/performance/SplayTest.java
+++ b/test/src/jdk/nashorn/internal/performance/SplayTest.java
@@ -27,10 +27,7 @@ package jdk.nashorn.internal.performance;
import org.testng.annotations.Test;
-/**
- *
- * @author Pavel Stepanov
- */
+@SuppressWarnings("javadoc")
public class SplayTest {
@Test
diff --git a/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java b/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
new file mode 100644
index 00000000..5c69141d
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static org.testng.Assert.fail;
+import java.io.File;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.ClassFilter;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.api.scripting.URLReader;
+import jdk.nashorn.internal.test.framework.TestFinder;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("javadoc")
+public class ClassFilterTest {
+ private static final String NASHORN_CODE_CACHE = "nashorn.persistent.code.cache";
+ private static final String CLASSFILTER_CODE_CACHE = "build/classfilter_nashorn_code_cache";
+
+ // @Test
+ // This test takes too much time for basic "ant clean test" run.
+ // Given that "allow-all-java-classes" is equivalent to no java class
+ // filter and external tests don't access any java, not sure if this
+ // test contributes much. We need faster "ant clean test" cycle for
+ // developers.
+ public void runExternalJsTest() {
+ final String[] paths = new String[]{
+ "test/script/basic/compile-octane.js",
+ "test/script/basic/jquery.js",
+ "test/script/basic/prototype.js",
+ "test/script/basic/runsunspider.js",
+ "test/script/basic/underscore.js",
+ "test/script/basic/yui.js",
+ "test/script/basic/run-octane.js"
+ };
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ for (final String path : paths) {
+ final ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter());
+ try {
+ engine.eval(new URLReader(new File(path).toURI().toURL()));
+ } catch (final Exception e) {
+ fail("Script " + path + " fails with exception :" + e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void noJavaOptionTest() {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter());
+ try {
+ engine.eval("var str = Java.type('java.lang.String');");
+ fail("TypeError should have been thrown");
+ } catch (final ScriptException e) {
+ //emtpy
+ }
+ }
+
+ @Test
+ public void securityTest() {
+ if (System.getSecurityManager() == null) {
+ return;
+ }
+
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine engine = factory.getScriptEngine(getClassFilter());
+ try {
+ engine.eval("var thread = Java.type('sun.misc.Unsafe')");
+ fail("SecurityException should have been thrown");
+ } catch (final Exception e) {
+ //empty
+ }
+ try {
+ engine.eval("var thread = new sun.misc.Unsafe()");
+ fail("SecurityException should have been thrown");
+ } catch (final Exception e) {
+ //empty
+ }
+ try {
+ engine.eval("var thread = Java.extend(sun.misc.Unsafe, {})");
+ fail("TypeError should have been thrown");
+ } catch (final Exception e) {
+ //empty
+ }
+ try {
+ engine.eval("java.lang.System.exit(0)");
+ fail("SecurityException should have been thrown");
+ } catch (final Exception e) {
+ //empty
+ }
+
+ }
+
+ @Test
+ public void persistentCacheTest() {
+ final String oldCodeCache = System.getProperty(NASHORN_CODE_CACHE);
+ System.setProperty(NASHORN_CODE_CACHE, CLASSFILTER_CODE_CACHE);
+ try {
+ persistentCacheTestImpl();
+ } finally {
+ if (oldCodeCache != null) {
+ System.setProperty(NASHORN_CODE_CACHE, oldCodeCache);
+ }
+ }
+ }
+
+ private void persistentCacheTestImpl() {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine engine = factory.getScriptEngine(
+ TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
+ getClass().getClassLoader(),
+ getClassFilter()
+ );
+ final String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore();
+ try {
+ engine.eval(testScript);
+ } catch (final ScriptException exc) {
+ fail(exc.getMessage());
+ }
+ final ScriptEngine engineSafe = factory.getScriptEngine(
+ TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
+ getClass().getClassLoader(),
+ new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String s) {
+ return false;
+ }
+ }
+ );
+ try {
+ engineSafe.eval(testScript);
+ fail("ClassNotFoundException should have been thrown");
+ } catch (final Exception exc) {
+ if (!(exc.getCause() instanceof ClassNotFoundException)) {
+ fail("ClassNotFoundException expected, got " + exc.getClass());
+ }
+ }
+ }
+
+ private static String generateCodeForPersistentStore() {
+ final StringBuilder stringBuilder = new StringBuilder();
+ for (int i=0; i < 100; i++) {
+ stringBuilder.append("function i")
+ .append(i)
+ .append("(y, z) { var x")
+ .append(i)
+ .append(" = ")
+ .append(i)
+ .append(";}");
+ }
+ return stringBuilder.toString();
+ }
+
+ private static ClassFilter getClassFilter() {
+ return new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String s) {
+ return true;
+ }
+ };
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
index a2d72ebf..2ca4820b 100644
--- a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
@@ -24,18 +24,18 @@
*/
package jdk.nashorn.internal.runtime;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.DirectoryStream;
-import java.nio.file.Path;
import java.nio.file.FileSystems;
-import javax.script.ScriptException;
-import org.testng.annotations.Test;
+import java.nio.file.Files;
+import java.nio.file.Path;
import javax.script.ScriptEngine;
+import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
/**
* @test
@@ -43,7 +43,7 @@ import static org.testng.Assert.assertEquals;
* @summary Test for persistent code cache and path handling
* @run testng jdk.nashorn.internal.runtime.CodeStoreAndPathTest
*/
-
+@SuppressWarnings("javadoc")
public class CodeStoreAndPathTest {
final String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; "
@@ -95,27 +95,23 @@ public class CodeStoreAndPathTest {
final String codeCache = "build/nashorn_code_cache";
final String oldUserDir = System.getProperty("user.dir");
- public void checkCompiledScripts(DirectoryStream<Path> stream, int numberOfScripts) throws IOException {
- for (Path file : stream) {
- numberOfScripts--;
- }
- stream.close();
- assertEquals(numberOfScripts,0);
- }
+ private static final String[] ENGINE_OPTIONS_OPT = new String[]{"--persistent-code-cache", "--optimistic-types=true"};
+ private static final String[] ENGINE_OPTIONS_NOOPT = new String[]{"--persistent-code-cache", "--optimistic-types=false"};
@Test
- public void pathHandlingTest() throws ScriptException, IOException {
+ public void pathHandlingTest() {
System.setProperty("nashorn.persistent.code.cache", codeCache);
- String[] options = new String[]{"--persistent-code-cache"};
- NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
- ScriptEngine e = fac.getScriptEngine(options);
- Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache);
- Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+
+ fac.getScriptEngine(ENGINE_OPTIONS_NOOPT);
+
+ final Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache);
+ final Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty(
"nashorn.persistent.code.cache")).toAbsolutePath();
// Check that nashorn code cache is created in current working directory
assertEquals(actualCodeCachePath, expectedCodeCachePath);
// Check that code cache dir exists and it's not empty
- File file = new File(actualCodeCachePath.toUri());
+ final File file = new File(actualCodeCachePath.toUri());
assertFalse(!file.isDirectory(), "No code cache directory was created!");
assertFalse(file.list().length == 0, "Code cache directory is empty!");
}
@@ -123,37 +119,70 @@ public class CodeStoreAndPathTest {
@Test
public void changeUserDirTest() throws ScriptException, IOException {
System.setProperty("nashorn.persistent.code.cache", codeCache);
- String[] options = new String[]{"--persistent-code-cache"};
- NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
- ScriptEngine e = fac.getScriptEngine(options);
- Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
- "nashorn.persistent.code.cache")).toAbsolutePath();
- String newUserDir = "build/newUserDir";
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_NOOPT);
+ final Path codeCachePath = getCodeCachePath(false);
+ final String newUserDir = "build/newUserDir";
// Now changing current working directory
System.setProperty("user.dir", System.getProperty("user.dir") + File.separator + newUserDir);
- // Check that a new compiled script is stored in exisitng code cache
+ try {
+ // Check that a new compiled script is stored in existing code cache
+ e.eval(code1);
+ final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+ checkCompiledScripts(stream, 1);
+ // Setting to default current working dir
+ } finally {
+ System.setProperty("user.dir", oldUserDir);
+ }
+ }
+
+ @Test
+ public void codeCacheTest() throws ScriptException, IOException {
+ System.setProperty("nashorn.persistent.code.cache", codeCache);
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_NOOPT);
+ final Path codeCachePath = getCodeCachePath(false);
e.eval(code1);
- DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
- // Already one compiled script has been stored in the cache during initialization
+ e.eval(code2);
+ e.eval(code3);// less than minimum size for storing
+ // adding code1 and code2.
+ final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
checkCompiledScripts(stream, 2);
- // Setting to default current working dir
- System.setProperty("user.dir", oldUserDir);
}
@Test
- public void codeCacheTest() throws ScriptException, IOException {
+ public void codeCacheTestOpt() throws ScriptException, IOException {
System.setProperty("nashorn.persistent.code.cache", codeCache);
- String[] options = new String[]{"--persistent-code-cache"};
- NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
- ScriptEngine e = fac.getScriptEngine(options);
- Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
- "nashorn.persistent.code.cache")).toAbsolutePath();
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_OPT);
+ final Path codeCachePath = getCodeCachePath(true);
e.eval(code1);
e.eval(code2);
e.eval(code3);// less than minimum size for storing
- // Already one compiled script has been stored in the cache during initialization
// adding code1 and code2.
- DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
- checkCompiledScripts(stream, 3);
+ final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+ checkCompiledScripts(stream, 2);
}
+
+ private static Path getCodeCachePath(final boolean optimistic) {
+ final String codeCache = System.getProperty("nashorn.persistent.code.cache");
+ final Path codeCachePath = FileSystems.getDefault().getPath(codeCache).toAbsolutePath();
+ final String[] files = codeCachePath.toFile().list();
+ for (final String file : files) {
+ if (file.endsWith("_opt") == optimistic) {
+ return codeCachePath.resolve(file);
+ }
+ }
+ throw new AssertionError("Code cache path not found");
+ }
+
+ private static void checkCompiledScripts(final DirectoryStream<Path> stream, final int numberOfScripts) throws IOException {
+ int n = numberOfScripts;
+ for (@SuppressWarnings("unused") final Path file : stream) {
+ n--;
+ }
+ stream.close();
+ assertEquals(n, 0);
+ }
+
}
diff --git a/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java b/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
new file mode 100644
index 00000000..16c36068
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+/**
+ * Tests for JSType methods.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.ConsStringTest
+ */
+public class ConsStringTest {
+
+ /**
+ * Test toString conversion
+ */
+ @Test
+ public void testConsStringToString() {
+ final ConsString cs1 = new ConsString("b", "c");
+ final ConsString cs2 = new ConsString("d", "e");
+ final ConsString cs3 = new ConsString(cs1, cs2);
+ final ConsString cs4 = new ConsString(cs3, "f");
+ final ConsString cs5 = new ConsString("a", cs4);
+ assertEquals(cs5.toString(), "abcdef");
+ assertEquals(cs4.toString(), "bcdef");
+ assertEquals(cs3.toString(), "bcde");
+ assertEquals(cs2.toString(), "de");
+ assertEquals(cs1.toString(), "bc");
+ // ConsStrings should be flattened now
+ assertEquals(cs1.getComponents()[0], "bc");
+ assertEquals(cs1.getComponents()[1], "");
+ assertEquals(cs2.getComponents()[0], "de");
+ assertEquals(cs2.getComponents()[1], "");
+ assertEquals(cs3.getComponents()[0], "bcde");
+ assertEquals(cs3.getComponents()[1], "");
+ assertEquals(cs4.getComponents()[0], "bcdef");
+ assertEquals(cs4.getComponents()[1], "");
+ assertEquals(cs5.getComponents()[0], "abcdef");
+ assertEquals(cs5.getComponents()[1], "");
+ }
+
+ /**
+ * Test charAt
+ */
+ @Test
+ public void testConsStringCharAt() {
+ final ConsString cs1 = new ConsString("b", "c");
+ final ConsString cs2 = new ConsString("d", "e");
+ final ConsString cs3 = new ConsString(cs1, cs2);
+ final ConsString cs4 = new ConsString(cs3, "f");
+ final ConsString cs5 = new ConsString("a", cs4);
+ assertEquals(cs1.charAt(1), 'c');
+ assertEquals(cs2.charAt(0), 'd');
+ assertEquals(cs3.charAt(3), 'e');
+ assertEquals(cs4.charAt(1), 'c');
+ assertEquals(cs5.charAt(2), 'c');
+ // ConsStrings should be flattened now
+ assertEquals(cs1.getComponents()[0], "bc");
+ assertEquals(cs1.getComponents()[1], "");
+ assertEquals(cs2.getComponents()[0], "de");
+ assertEquals(cs2.getComponents()[1], "");
+ assertEquals(cs3.getComponents()[0], "bcde");
+ assertEquals(cs3.getComponents()[1], "");
+ assertEquals(cs4.getComponents()[0], "bcdef");
+ assertEquals(cs4.getComponents()[1], "");
+ assertEquals(cs5.getComponents()[0], "abcdef");
+ assertEquals(cs5.getComponents()[1], "");
+ }
+
+
+ /**
+ * Test flattening of top-level and internal ConsStrings
+ */
+ @Test
+ public void testConsStringFlattening() {
+ final ConsString cs1 = new ConsString("b", "c");
+ final ConsString cs2 = new ConsString("d", "e");
+ final ConsString cs3 = new ConsString(cs1, cs2);
+ final ConsString cs4 = new ConsString(cs3, "f");
+
+ final ConsString cs5 = new ConsString("a", cs4);
+ // top-level ConsString should not yet be flattened
+ assert(cs5.getComponents()[0] == "a");
+ assert(cs5.getComponents()[1] == cs4);
+ assertEquals(cs5.toString(), "abcdef");
+ // top-level ConsString should be flattened
+ assertEquals(cs5.getComponents()[0], "abcdef");
+ assertEquals(cs5.getComponents()[1], "");
+ // internal ConsString should not yet be flattened after first traversal
+ assertEquals(cs4.getComponents()[0], cs3);
+ assertEquals(cs4.getComponents()[1], "f");
+
+ final ConsString cs6 = new ConsString("a", cs4);
+ // top-level ConsString should not yet be flattened
+ assertEquals(cs6.getComponents()[0], "a");
+ assertEquals(cs6.getComponents()[1], cs4);
+ assertEquals(cs6.toString(), "abcdef");
+ // top-level ConsString should be flattened
+ assertEquals(cs6.getComponents()[0], "abcdef");
+ assertEquals(cs6.getComponents()[1], "");
+ // internal ConsString should have been flattened after second traversal
+ assertEquals(cs4.getComponents()[0], "bcdef");
+ assertEquals(cs4.getComponents()[1], "");
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/test/src/jdk/nashorn/internal/runtime/ContextTest.java
index 4c4a8c65..6770d7ec 100644
--- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java
@@ -28,7 +28,7 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-
+import static org.testng.Assert.fail;
import java.util.Map;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.options.Options;
@@ -40,6 +40,7 @@ import org.testng.annotations.Test;
* @test
* @run testng jdk.nashorn.internal.runtime.ContextTest
*/
+@SuppressWarnings("javadoc")
public class ContextTest {
// basic context eval test
@Test
@@ -60,6 +61,27 @@ public class ContextTest {
}
}
+ // Make sure trying to compile an invalid script returns null - see JDK-8046215.
+ @Test
+ public void compileErrorTest() {
+ final Options options = new Options("");
+ final ErrorManager errors = new ErrorManager();
+ final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
+ final Global oldGlobal = Context.getGlobal();
+ Context.setGlobal(cx.createGlobal());
+ try {
+ final ScriptFunction script = cx.compileScript(sourceFor("<evalCompileErrorTest>", "*/"), Context.getGlobal());
+ if (script != null) {
+ fail("Invalid script compiled without errors");
+ }
+ if (errors.getNumberOfErrors() != 1) {
+ fail("Wrong number of errors: " + errors.getNumberOfErrors());
+ }
+ } finally {
+ Context.setGlobal(oldGlobal);
+ }
+ }
+
// basic check for JS reflection access - java.util.Map-like access on ScriptObject
@Test
public void reflectionTest() {
@@ -74,7 +96,7 @@ public class ContextTest {
final String code = "var obj = { x: 344, y: 42 }";
eval(cx, "<reflectionTest>", code);
- final Object obj = cx.getGlobal().get("obj");
+ final Object obj = Context.getGlobal().get("obj");
assertTrue(obj instanceof ScriptObject);
@@ -107,7 +129,7 @@ public class ContextTest {
}
}
- private Object eval(final Context cx, final String name, final String code) {
+ private static Object eval(final Context cx, final String name, final String code) {
final Source source = sourceFor(name, code);
final ScriptObject global = Context.getGlobal();
final ScriptFunction func = cx.compileScript(source, global);
diff --git a/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java b/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
new file mode 100644
index 00000000..3b6d91b2
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectOutputStream;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.Test;
+
+/**
+ * JDK-8044518: Ensure exceptions related to optimistic recompilation are not serializable
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.ExceptionsNotSerializable
+ */
+@SuppressWarnings("javadoc")
+public class ExceptionsNotSerializable {
+ @Test
+ public void rewriteExceptionNotSerializable() throws ScriptException {
+ // NOTE: we must create a RewriteException in a context of a Nashorn engine, as it uses Global.newIntance()
+ // internally.
+ final ScriptEngine e = new NashornScriptEngineFactory().getScriptEngine();
+ e.put("f", new Runnable() {
+ @Override
+ public void run() {
+ tryToSerialize(RewriteException.create(null, new Object[0], new String[0]));
+ }
+ });
+ e.eval("f()");
+ }
+
+ @Test
+ public void unwarrantedOptimismExceptionNotSerializable() {
+ tryToSerialize(new UnwarrantedOptimismException(new Double(1.0), 128));
+ }
+
+ private static void tryToSerialize(final Object obj) {
+ try {
+ new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(obj);
+ fail();
+ } catch (final NotSerializableException e) {
+ assertEquals(e.getMessage(), obj.getClass().getName());
+ } catch (final IOException e) {
+ fail("", e);
+ }
+
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java b/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
new file mode 100644
index 00000000..2cd0bf01
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.Test;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Top-level lexical binding tests.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
+ */
+@SuppressWarnings("javadoc")
+public class LexicalBindingTest {
+
+ final static String LANGUAGE_ES6 = "--language=es6";
+ final static int NUMBER_OF_CONTEXTS = 20;
+ final static int MEGAMORPHIC_LOOP_COUNT = 20;
+
+ /**
+ * Test access to global var-declared variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void megamorphicVarTest() throws ScriptException, InterruptedException {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine e = factory.getScriptEngine();
+ final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
+ final String sharedScript = "foo";
+
+
+ for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+ final ScriptContext context = contexts[i] = new SimpleScriptContext();
+ final Bindings b = e.createBindings();
+ context.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ assertEquals(e.eval("var foo = '" + i + "';", context), null);
+ }
+
+ for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+ final ScriptContext context = contexts[i];
+ assertEquals(e.eval(sharedScript, context), String.valueOf(i));
+ }
+ }
+
+ /**
+ * Test access to global lexically declared variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void megamorphicMultiGlobalLetTest() throws ScriptException, InterruptedException {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+ final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
+ final String sharedScript = "foo";
+
+
+ for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+ final ScriptContext context = contexts[i] = new SimpleScriptContext();
+ final Bindings b = e.createBindings();
+ context.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ assertEquals(e.eval("let foo = '" + i + "';", context), null);
+ }
+
+ for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+ final ScriptContext context = contexts[i];
+ assertEquals(e.eval(sharedScript, context), String.valueOf(i));
+ }
+ }
+
+
+ /**
+ * Test access to global lexically declared variables for shared script classes with single global.
+ */
+ @Test
+ public static void megamorphicSingleGlobalLetTest() throws ScriptException, InterruptedException {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+ final String sharedGetterScript = "foo";
+ final String sharedSetterScript = "foo = 1";
+
+ for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
+ assertEquals(e.eval(sharedSetterScript), 1);
+ assertEquals(e.eval(sharedGetterScript), 1);
+ assertEquals(e.eval("delete foo; a" + i + " = 1; foo = " + i + ";"), i);
+ assertEquals(e.eval(sharedGetterScript), i);
+ }
+
+ assertEquals(e.eval("let foo = 'foo';"), null);
+ assertEquals(e.eval(sharedGetterScript), "foo");
+ assertEquals(e.eval(sharedSetterScript), 1);
+ assertEquals(e.eval(sharedGetterScript), 1);
+ assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
+ }
+
+ /**
+ * Test access to global lexically declared variables for shared script classes with single global.
+ */
+ @Test
+ public static void megamorphicInheritedGlobalLetTest() throws ScriptException, InterruptedException {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+ final String sharedGetterScript = "foo";
+ final String sharedSetterScript = "foo = 1";
+
+ for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
+ assertEquals(e.eval(sharedSetterScript), 1);
+ assertEquals(e.eval(sharedGetterScript), 1);
+ assertEquals(e.eval("delete foo; a" + i + " = 1; Object.prototype.foo = " + i + ";"), i);
+ assertEquals(e.eval(sharedGetterScript), i);
+ }
+
+ assertEquals(e.eval("let foo = 'foo';"), null);
+ assertEquals(e.eval(sharedGetterScript), "foo");
+ assertEquals(e.eval(sharedSetterScript), 1);
+ assertEquals(e.eval(sharedGetterScript), 1);
+ assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
+ }
+
+ /**
+ * Test multi-threaded access to global lexically declared variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedLetTest() throws ScriptException, InterruptedException {
+ final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+ final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "foo";
+
+ assertEquals(e.eval("let foo = 'original context';", origContext), null);
+ assertEquals(e.eval("let foo = 'new context';", newCtxt), null);
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval("foo = 'newer context';", newCtxt), "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ assertEquals(e.eval(sharedScript), "original context");
+ assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ private static class ScriptRunner implements Runnable {
+
+ final ScriptEngine engine;
+ final ScriptContext context;
+ final String source;
+ final Object expected;
+ final int iterations;
+
+ ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
+ this.engine = engine;
+ this.context = context;
+ this.source = source;
+ this.expected = expected;
+ this.iterations = iterations;
+ }
+
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < iterations; i++) {
+ assertEquals(engine.eval(source, context), expected);
+ }
+ } catch (final ScriptException se) {
+ throw new RuntimeException(se);
+ }
+ }
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
index 7b84f5a7..91f19606 100644
--- a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
@@ -24,13 +24,11 @@
*/
package jdk.nashorn.internal.runtime;
+import static org.testng.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static org.testng.Assert.fail;
-import org.testng.annotations.Test;
-
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
@@ -39,6 +37,7 @@ import javax.script.SimpleScriptContext;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
/**
* @test
@@ -46,6 +45,7 @@ import org.testng.annotations.BeforeTest;
* @summary Sanity tests for no persistence caching
* @run testng/othervm jdk.nashorn.internal.runtime.NoPersistenceCachingTest
*/
+@SuppressWarnings("javadoc")
public class NoPersistenceCachingTest {
private ScriptEngine engine;
@@ -59,8 +59,8 @@ public class NoPersistenceCachingTest {
prevStderr = System.err;
System.setErr(new PrintStream(stderr));
NashornScriptEngineFactory nashornFactory = null;
- ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ final ScriptEngineManager sm = new ScriptEngineManager();
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
nashornFactory = (NashornScriptEngineFactory) fac;
break;
@@ -69,7 +69,10 @@ public class NoPersistenceCachingTest {
if (nashornFactory == null) {
fail("Cannot find nashorn factory!");
}
- String[] options = new String[]{"--log=compiler:finest"};
+ // fine is enough for cache hits, finest produces way too much information
+ // TODO this should be ported to use the RuntimeEvents instead of screen scraping
+ // logs, as obviously this is very brittle
+ final String[] options = new String[]{"--log=compiler:fine"};
engine = nashornFactory.getScriptEngine(options);
context1 = engine.getContext();
context2 = new SimpleScriptContext();
@@ -83,29 +86,31 @@ public class NoPersistenceCachingTest {
System.setErr(prevStderr);
}
- public void runTest(int numberOfContext, String expectedOutputPattern,
- int expectedPatternOccurrence) {
+ public void runTest(final int numberOfContext, final String expectedOutputPattern,
+ final int expectedPatternOccurrence) {
try {
switch (numberOfContext) {
case 2:
- String scriptTwoContexts = "print('HelloTwoContexts')";
+ final String scriptTwoContexts = "print('HelloTwoContexts')";
engine.eval(scriptTwoContexts, context1);
engine.eval(scriptTwoContexts, context2);
break;
case 3:
- String scriptThreeContexts = "print('HelloThreeContexts')";
+ final String scriptThreeContexts = "print('HelloThreeContexts')";
engine.eval(scriptThreeContexts, context1);
engine.eval(scriptThreeContexts, context2);
engine.eval(scriptThreeContexts, context3);
break;
+ default:
+ break;
}
} catch (final Exception se) {
se.printStackTrace();
fail(se.getMessage());
}
- Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
- Matcher matcher = deoptimizing.matcher(stderr.toString());
+ final Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
+ final Matcher matcher = deoptimizing.matcher(stderr.toString());
int matches = 0;
while (matcher.find()) {
matches++;
diff --git a/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/test/src/jdk/nashorn/internal/runtime/SourceTest.java
index 34635856..12645c05 100644
--- a/test/src/jdk/nashorn/internal/runtime/SourceTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/SourceTest.java
@@ -25,24 +25,23 @@
package jdk.nashorn.internal.runtime;
-import jdk.nashorn.api.scripting.URLReader;
-import org.testng.annotations.Test;
-
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Arrays;
-
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import jdk.nashorn.api.scripting.URLReader;
+import org.testng.annotations.Test;
/**
* Tests different Source representations.
*/
+@SuppressWarnings("javadoc")
public class SourceTest {
final private static String SOURCE_NAME = "source.js";
@@ -105,11 +104,11 @@ public class SourceTest {
}
}
- private Reader getReader(final String path) {
+ private static Reader getReader(final String path) {
return new InputStreamReader(SourceTest.class.getResourceAsStream(path));
}
- private void testSources(final Source source1, final Source source2) {
+ private static void testSources(final Source source1, final Source source2) {
final char[] chars1 = source1.getContent();
final char[] chars2 = source2.getContent();
final String str1 = source1.getString();
@@ -118,9 +117,6 @@ public class SourceTest {
assertEquals(str1, str2);
assertEquals(source1.hashCode(), source2.hashCode());
assertTrue(source1.equals(source2));
- // Test for immutability
- Arrays.fill(source1.getContent(), (char)0);
- Arrays.fill(source2.getContent(), (char)1);
assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray()));
assertTrue(Arrays.equals(source1.getContent(), chars1));
assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));
diff --git a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
index f6da6f82..09c90dc6 100644
--- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
@@ -28,20 +28,20 @@ package jdk.nashorn.internal.runtime;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-
+import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
-import javax.script.ScriptContext;
import javax.script.ScriptException;
-import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
import org.testng.annotations.Test;
/**
* Tests for trusted client usage of nashorn script engine factory extension API
*/
+@SuppressWarnings("javadoc")
public class TrustedScriptEngineTest {
@Test
public void versionTest() {
@@ -55,7 +55,7 @@ public class TrustedScriptEngineTest {
private final boolean[] reached = new boolean[1];
@Override
- protected Class findClass(final String name) throws ClassNotFoundException {
+ protected Class<?> findClass(final String name) throws ClassNotFoundException {
// flag that it reached here
reached[0] = true;
return super.findClass(name);
@@ -64,7 +64,7 @@ public class TrustedScriptEngineTest {
public boolean reached() {
return reached[0];
}
- };
+ }
// These are for "private" extension API of NashornScriptEngineFactory that
// accepts a ClassLoader and/or command line options.
@@ -72,7 +72,7 @@ public class TrustedScriptEngineTest {
@Test
public void factoryClassLoaderTest() {
final ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
final MyClassLoader loader = new MyClassLoader();
@@ -96,7 +96,7 @@ public class TrustedScriptEngineTest {
@Test
public void factoryClassLoaderAndOptionsTest() {
final ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
final String[] options = new String[] { "-strict" };
@@ -130,7 +130,7 @@ public class TrustedScriptEngineTest {
@Test
public void factoryOptionsTest() {
final ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
// specify --no-syntax-extensions flag
@@ -140,7 +140,8 @@ public class TrustedScriptEngineTest {
// try nashorn specific extension
e.eval("var f = funtion(x) 2*x;");
fail("should have thrown exception!");
- } catch (final ScriptException se) {
+ } catch (final Exception ex) {
+ //empty
}
return;
}
@@ -156,7 +157,7 @@ public class TrustedScriptEngineTest {
*/
public void noLoaderPerCompilerTest() {
final ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
final String[] options = new String[] { "--loader-per-compile=false" };
@@ -181,7 +182,7 @@ public class TrustedScriptEngineTest {
*/
public void noLoaderPerCompilerWithSameNameTest() {
final ScriptEngineManager sm = new ScriptEngineManager();
- for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
if (fac instanceof NashornScriptEngineFactory) {
final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
final String[] options = new String[] { "--loader-per-compile=false" };
@@ -221,8 +222,106 @@ public class TrustedScriptEngineTest {
assertTrue(e.eval("typeof bar").equals("function"));
}
+ @Test
+ public void classFilterTest() throws ScriptException {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine e = fac.getScriptEngine(new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String fullName) {
+ // don't allow anything that is not "java."
+ return fullName.startsWith("java.");
+ }
+ });
+
+ assertEquals(e.eval("typeof javax.script.ScriptEngine"), "object");
+ assertEquals(e.eval("typeof java.util.Vector"), "function");
+
+ try {
+ e.eval("Java.type('javax.script.ScriptContext')");
+ fail("should not reach here");
+ } catch (final ScriptException | RuntimeException se) {
+ if (! (se.getCause() instanceof ClassNotFoundException)) {
+ fail("ClassNotFoundException expected");
+ }
+ }
+ }
+
+ @Test
+ public void classFilterTest2() throws ScriptException {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine e = fac.getScriptEngine(new String[0], Thread.currentThread().getContextClassLoader(),
+ new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String fullName) {
+ // don't allow anything that is not "java."
+ return fullName.startsWith("java.");
+ }
+ });
+
+ assertEquals(e.eval("typeof javax.script.ScriptEngine"), "object");
+ assertEquals(e.eval("typeof java.util.Vector"), "function");
+
+ try {
+ e.eval("Java.type('javax.script.ScriptContext')");
+ fail("should not reach here");
+ } catch (final ScriptException | RuntimeException se) {
+ if (! (se.getCause() instanceof ClassNotFoundException)) {
+ fail("ClassNotFoundException expected");
+ }
+ }
+ }
+
+ @Test
+ public void nullClassFilterTest() {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine((ClassFilter)null);
+ fail("should have thrown NPE");
+ } catch (final NullPointerException e) {
+ //empty
+ }
+ }
+
+ @Test
+ public void nullClassFilterTest2() {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine(new String[0], null, null);
+ fail("should have thrown NPE");
+ } catch (final NullPointerException e) {
+ //empty
+ }
+ }
+
+ @Test
+ public void nullArgsTest() {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine((String[])null);
+ fail("should have thrown NPE");
+ } catch (final NullPointerException e) {
+ //empty
+ }
+ }
+
+ @Test
+ public void nullArgsTest2() {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ try {
+ fac.getScriptEngine(null, null, new ClassFilter() {
+ @Override
+ public boolean exposeToScripts(final String name) {
+ return true;
+ }
+ });
+ fail("should have thrown NPE");
+ } catch (final NullPointerException e) {
+ //empty
+ }
+ }
- @Test public void nashornSwallowsConstKeyword() throws Exception {
+ @Test
+ public void nashornSwallowsConstKeyword() throws Exception {
final NashornScriptEngineFactory f = new NashornScriptEngineFactory();
final String[] args = new String[] { "--const-as-var" };
final ScriptEngine engine = f.getScriptEngine(args);
@@ -235,4 +334,29 @@ public class TrustedScriptEngineTest {
);
assertEquals(ret, 10, "Parsed and executed OK");
}
+
+ @Test
+ public void evalDefaultFileNameTest() throws ScriptException {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" });
+ // default FILENAME being "<eval>" make sure generated code bytecode verifies.
+ engine.eval("var a = 3;");
+ }
+
+ @Test
+ public void evalFileNameWithSpecialCharsTest() throws ScriptException {
+ final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" });
+ final ScriptContext ctxt = new SimpleScriptContext();
+ // use file name with "dangerous" chars.
+ ctxt.setAttribute(ScriptEngine.FILENAME, "<myscript>", ScriptContext.ENGINE_SCOPE);
+ engine.eval("var a = 3;");
+ ctxt.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE);
+ engine.eval("var h = 'hello';");
+ ctxt.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE);
+ engine.eval("var foo = 'world';");
+ // name used by jjs shell tool for the interactive mode
+ ctxt.setAttribute(ScriptEngine.FILENAME, "<shell>", ScriptContext.ENGINE_SCOPE);
+ engine.eval("var foo = 'world';");
+ }
}
diff --git a/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java b/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
index c22838fb..8156b786 100644
--- a/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
@@ -29,7 +29,6 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
-import jdk.nashorn.internal.runtime.ParserException;
import org.testng.annotations.Test;
/**
@@ -45,8 +44,8 @@ public class JdkRegExpTest {
*/
@Test
public void testMatcher() {
- RegExp regexp = new RegExpFactory().compile("f(o)o", "");
- RegExpMatcher matcher = regexp.match("foo");
+ final RegExp regexp = new RegExpFactory().compile("f(o)o", "");
+ final RegExpMatcher matcher = regexp.match("foo");
assertNotNull(matcher);
assertTrue(matcher.search(0));
assertEquals(matcher.getInput(), "foo");
diff --git a/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java b/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
index a6981c8d..616f769f 100644
--- a/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
@@ -25,9 +25,6 @@
package jdk.nashorn.internal.runtime.regexp.joni;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
import org.testng.annotations.Test;
/**
@@ -36,6 +33,7 @@ import org.testng.annotations.Test;
* @test
* @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest
*/
+@SuppressWarnings("javadoc")
public class JoniTest {
@Test
diff --git a/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java b/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
index 07ff6f96..e8ca191d 100644
--- a/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
+++ b/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
@@ -34,7 +34,6 @@ import static jdk.nashorn.internal.test.framework.TestConfig.OPTIONS_IGNORE_STD_
import static jdk.nashorn.internal.test.framework.TestConfig.OPTIONS_RUN;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_FAIL_LIST;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_SHARED_CONTEXT;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -50,6 +49,7 @@ import java.util.regex.Matcher;
/**
* Abstract class to compile and run one .js script file.
*/
+@SuppressWarnings("javadoc")
public abstract class AbstractScriptRunnable {
// some test scripts need a "framework" script - whose features are used
// in the test script. This optional framework script can be null.
@@ -155,7 +155,7 @@ public abstract class AbstractScriptRunnable {
// VM options when a @fork test is executed by a separate process
protected static final String[] forkJVMOptions;
static {
- String vmOptions = System.getProperty(TestConfig.TEST_FORK_JVM_OPTIONS);
+ final String vmOptions = System.getProperty(TestConfig.TEST_FORK_JVM_OPTIONS);
forkJVMOptions = (vmOptions != null)? vmOptions.split(" ") : new String[0];
}
@@ -274,14 +274,14 @@ public abstract class AbstractScriptRunnable {
// compile and run this script
protected abstract void execute();
- private boolean equalsCompilerMsgs(final String es, final String as) {
+ private static boolean equalsCompilerMsgs(final String es, final String as) {
final int split = es.indexOf(':');
// Replace both types of separators ('/' and '\') with the one from
// current environment
return (split >= 0) && as.equals(es.substring(0, split).replaceAll("[/\\\\]", Matcher.quoteReplacement(File.separator)) + es.substring(split));
}
- private void escape(final String value, final StringBuilder out) {
+ private static void escape(final String value, final StringBuilder out) {
final int len = value.length();
for (int i = 0; i < len; i++) {
final char ch = value.charAt(i);
@@ -297,7 +297,7 @@ public abstract class AbstractScriptRunnable {
}
}
- private String escape(final String value) {
+ private static String escape(final String value) {
final StringBuilder sb = new StringBuilder();
escape(value, sb);
return sb.toString();
diff --git a/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java b/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
index 7f6bd8fd..fe8fa710 100644
--- a/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
+++ b/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
@@ -34,7 +34,7 @@ import org.testng.reporters.JUnitReportReporter;
*/
public class JSJUnitReportReporter extends JUnitReportReporter {
@Override
- protected String getTestName(ITestResult tr) {
+ protected String getTestName(final ITestResult tr) {
final String testName = tr.getTestName();
return (testName != null && testName.endsWith(".js"))? testName : super.getTestName(tr);
}
diff --git a/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java b/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java
index c9c567d9..74b5ccd7 100644
--- a/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java
+++ b/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java
@@ -34,6 +34,7 @@ import org.testng.annotations.Test;
* Test case used by JSCompilerTest to complain if test files are marked as
* neither test nor subtest.
*/
+@SuppressWarnings("javadoc")
public final class OrphanTestFinder implements ITest {
private final Set<String> orphanFiles;
diff --git a/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java b/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
index d4269fce..2c206d7c 100644
--- a/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
+++ b/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
@@ -31,7 +31,6 @@ import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_EXCLUDES_FI
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_EXCLUDE_LIST;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_FRAMEWORK;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ROOTS;
-
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -73,12 +72,14 @@ import jdk.nashorn.internal.test.framework.TestFinder.TestFactory;
* Parallel test runner runs tests in multiple threads - but avoids any dependency
* on third-party test framework library such as TestNG.
*/
+@SuppressWarnings("javadoc")
public class ParallelTestRunner {
// ParallelTestRunner-specific
private static final String TEST_JS_THREADS = "test.js.threads";
private static final String TEST_JS_REPORT_FILE = "test.js.report.file";
- private static final int THREADS = Integer.getInteger(TEST_JS_THREADS, Runtime.getRuntime().availableProcessors());
+ // test262 does a lot of eval's and the JVM hates multithreaded class definition, so lower thread count is usually faster.
+ private static final int THREADS = Integer.getInteger(TEST_JS_THREADS, Runtime.getRuntime().availableProcessors() > 4 ? 4 : 2);
private final List<ScriptRunnable> tests = new ArrayList<>();
private final Set<String> orphans = new TreeSet<>();
@@ -149,7 +150,7 @@ public class ParallelTestRunner {
}
@Override
- protected void log(String msg) {
+ protected void log(final String msg) {
System.err.println(msg);
}
@@ -235,6 +236,7 @@ public class ParallelTestRunner {
outputFile.write(out.toByteArray());
errorFile.write(err.toByteArray());
}
+ ex.printStackTrace();
throw ex;
}
}
@@ -245,7 +247,7 @@ public class ParallelTestRunner {
}
}
- private void compare(final String outputFileName, final String expected, final boolean compareCompilerMsg) throws IOException {
+ private void compare(final String fileName, final String expected, final boolean compareCompilerMsg) throws IOException {
final File expectedFile = new File(expected);
BufferedReader expectedReader;
@@ -255,7 +257,7 @@ public class ParallelTestRunner {
expectedReader = new BufferedReader(new StringReader(""));
}
- final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(outputFileName)));
+ final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
compare(actual, expectedReader, compareCompilerMsg);
}
@@ -280,6 +282,7 @@ public class ParallelTestRunner {
} catch (final Throwable ex) {
result.exception = ex;
result.passed = false;
+ ex.printStackTrace();
}
return result;
}
@@ -306,12 +309,12 @@ public class ParallelTestRunner {
final TestFactory<ScriptRunnable> testFactory = new TestFactory<ScriptRunnable>() {
@Override
- public ScriptRunnable createTest(String framework, File testFile, List<String> engineOptions, Map<String, String> testOptions, List<String> arguments) {
+ public ScriptRunnable createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments) {
return new ScriptRunnable(framework, testFile, engineOptions, testOptions, arguments);
}
@Override
- public void log(String msg) {
+ public void log(final String msg) {
System.err.println(msg);
}
};
@@ -431,7 +434,9 @@ public class ParallelTestRunner {
public static void main(final String[] args) throws Exception {
parseArgs(args);
- while(new ParallelTestRunner().run());
+ while (new ParallelTestRunner().run()) {
+ //empty
+ }
}
private static void parseArgs(final String[] args) {
diff --git a/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java b/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
index 0f55a6fa..704b77c5 100644
--- a/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
+++ b/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
@@ -40,10 +40,8 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Map;
-
import jdk.nashorn.tools.Shell;
import org.testng.Assert;
import org.testng.ITest;
@@ -54,6 +52,7 @@ import org.testng.annotations.Test;
* class. Optionally, output from running the script is compared against the
* corresponding .EXPECTED file.
*/
+@SuppressWarnings("javadoc")
public final class ScriptRunnable extends AbstractScriptRunnable implements ITest {
public ScriptRunnable(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> scriptArguments) {
super(framework, testFile, engineOptions, testOptions, scriptArguments);
@@ -72,7 +71,11 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes
@Test
@Override
public void runTest() throws IOException {
- super.runTest();
+ try {
+ super.runTest();
+ } catch(final AssertionError e) {
+ throw new AssertionError("Failed executing test " + testFile, e);
+ }
}
@Override
@@ -86,7 +89,7 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes
// avoid direct System.out.println - use reporter to capture
@Override
- protected void log(String msg) {
+ protected void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@@ -174,8 +177,10 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes
cmd.add(System.getProperty("java.home") + separator + "bin" + separator + "java");
cmd.add("-Djava.ext.dirs=dist");
- for (String str : forkJVMOptions) {
- cmd.add(str);
+ for (final String str : forkJVMOptions) {
+ if(!str.isEmpty()) {
+ cmd.add(str);
+ }
}
cmd.add(Shell.class.getName());
// now add the rest of the "in process" runtime arguments
diff --git a/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java b/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
index acaf5424..70c2992f 100644
--- a/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
+++ b/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.test.framework;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_INCLUDES;
-
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -48,7 +47,9 @@ public final class ScriptTest {
* Creates a test factory for the set of .js source tests.
*
* @return a Object[] of test objects.
+ * @throws Exception upon failure
*/
+ @SuppressWarnings("static-method")
@Factory
public Object[] suite() throws Exception {
Locale.setDefault(new Locale(""));
@@ -63,7 +64,7 @@ public final class ScriptTest {
}
@Override
- public void log(String msg) {
+ public void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
};
diff --git a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
index 47ea7b32..b7844b92 100644
--- a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
+++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
@@ -74,21 +74,21 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
}
@Override
- public void write(byte[] b) throws IOException {
+ public void write(final byte[] b) throws IOException {
underlying.write(b);
}
@Override
- public void write(byte[] b, int off, int len) throws IOException {
+ public void write(final byte[] b, final int off, final int len) throws IOException {
underlying.write(b, off, len);
}
@Override
- public void write(int b) throws IOException {
+ public void write(final int b) throws IOException {
underlying.write(b);
}
- void setDelegatee(OutputStream stream) {
+ void setDelegatee(final OutputStream stream) {
this.underlying = stream;
}
}
@@ -100,11 +100,11 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
public SharedContextEvaluator(final String[] args) {
this.ctxOut = new DelegatingOutputStream(System.out);
this.ctxErr = new DelegatingOutputStream(System.err);
- PrintWriter wout = new PrintWriter(ctxOut, true);
- PrintWriter werr = new PrintWriter(ctxErr, true);
- Options options = new Options("nashorn", werr);
+ final PrintWriter wout = new PrintWriter(ctxOut, true);
+ final PrintWriter werr = new PrintWriter(ctxErr, true);
+ final Options options = new Options("nashorn", werr);
options.process(args);
- ErrorManager errors = new ErrorManager(werr);
+ final ErrorManager errors = new ErrorManager(werr);
this.context = new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
}
@@ -125,7 +125,7 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
continue;
}
final File file = new File(fileName);
- ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
+ final ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
if (script == null || errors.getNumberOfErrors() != 0) {
return COMPILATION_ERROR;
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestConfig.java b/test/src/jdk/nashorn/internal/test/framework/TestConfig.java
index 3b623038..e539ee2a 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestConfig.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestConfig.java
@@ -28,6 +28,7 @@ package jdk.nashorn.internal.test.framework;
/**
* Configuration info for script tests.
*/
+@SuppressWarnings("javadoc")
public interface TestConfig {
// Test options inferred from various test @foo tags and passed to test factory.
public static final String OPTIONS_RUN = "run";
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
index d879976d..32b1cbd5 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
@@ -42,11 +42,11 @@ import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_INCLUDES;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_LIST;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ROOTS;
import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_UNCHECKED_DIR;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
+import java.nio.ByteOrder;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
@@ -56,6 +56,7 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
@@ -75,7 +76,8 @@ import org.xml.sax.InputSource;
* Utility class to find/parse script test files and to create 'test' instances.
* Actual 'test' object type is decided by clients of this class.
*/
-final class TestFinder {
+@SuppressWarnings("javadoc")
+public final class TestFinder {
private TestFinder() {}
interface TestFactory<T> {
@@ -92,7 +94,7 @@ final class TestFinder {
final String testList = System.getProperty(TEST_JS_LIST);
final String failedTestFileName = System.getProperty(TEST_FAILED_LIST_FILE);
if(failedTestFileName != null) {
- File failedTestFile = new File(failedTestFileName);
+ final File failedTestFile = new File(failedTestFileName);
if(failedTestFile.exists() && failedTestFile.length() > 0L) {
try(final BufferedReader r = new BufferedReader(new FileReader(failedTestFile))) {
for(;;) {
@@ -195,7 +197,7 @@ final class TestFinder {
return false;
}
- private static <T> void handleOneTest(final String framework, final Path testFile, final List<T> tests, final Set<String> orphans, TestFactory<T> factory) throws Exception {
+ private static <T> void handleOneTest(final String framework, final Path testFile, final List<T> tests, final Set<String> orphans, final TestFactory<T> factory) throws Exception {
final String name = testFile.getFileName().toString();
assert name.lastIndexOf(".js") > 0 : "not a JavaScript: " + name;
@@ -215,6 +217,8 @@ final class TestFinder {
final List<String> scriptArguments = new ArrayList<>();
boolean inComment = false;
+ boolean explicitOptimistic = false;
+
try (Scanner scanner = new Scanner(testFile)) {
while (scanner.hasNext()) {
// TODO: Scan for /ref=file qualifiers, etc, to determine run
@@ -261,14 +265,23 @@ final class TestFinder {
isTest = false;
isNotTest = true;
break;
- case "@runif":
- if (System.getProperty(scanner.next()) != null) {
+ case "@bigendian":
+ shouldRun = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
+ break;
+ case "@littleendian":
+ shouldRun = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ break;
+ case "@runif": {
+ final String prop = scanner.next();
+ if (System.getProperty(prop) != null) {
shouldRun = true;
} else {
+ factory.log("WARNING: (" + prop + ") skipping " + testFile);
isTest = false;
isNotTest = true;
}
break;
+ }
case "@run":
shouldRun = true;
break;
@@ -284,11 +297,17 @@ final class TestFinder {
scriptArguments.add(scanner.next());
break;
case "@option":
- engineOptions.add(scanner.next());
+ final String next = scanner.next();
+ engineOptions.add(next);
+ if (next.startsWith("--optimistic-types")) {
+ explicitOptimistic = true;
+ }
break;
case "@fork":
fork = true;
break;
+ default:
+ break;
}
// negative tests are expected to fail at runtime only
@@ -333,12 +352,61 @@ final class TestFinder {
testOptions.put(OPTIONS_FORK, "true");
}
+ //if there are explicit optimistic type settings, use those - do not override
+ //the test might only work with optimistic types on or off.
+ if (!explicitOptimistic) {
+ addExplicitOptimisticTypes(engineOptions);
+ }
+
tests.add(factory.createTest(framework, testFile.toFile(), engineOptions, testOptions, scriptArguments));
} else if (!isNotTest) {
orphans.add(name);
}
}
+ //the reverse of the default setting for optimistic types, if enabled, false, otherwise true
+ //thus, true for 8u40, false for 9
+ private static final boolean OPTIMISTIC_OVERRIDE = true;
+
+ /**
+ * Check if there is an optimistic override, that disables the default
+ * false optimistic types and sets them to true, for testing purposes
+ *
+ * @return true if optimistic type override has been set by test suite
+ */
+ public static boolean hasOptimisticOverride() {
+ return Boolean.valueOf(OPTIMISTIC_OVERRIDE).toString().equals(System.getProperty("optimistic.override"));
+ }
+
+ /**
+ * Add an optimistic-types=true option to an argument list if this
+ * is set to override the default false. Add an optimistic-types=true
+ * options to an argument list if this is set to override the default
+ * true
+ *
+ * @args new argument list array
+ */
+ public static String[] addExplicitOptimisticTypes(final String[] args) {
+ if (hasOptimisticOverride()) {
+ final List<String> newList = new ArrayList<>(Arrays.asList(args));
+ newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
+ return newList.toArray(new String[0]);
+ }
+ return args;
+ }
+
+ /**
+ * Add an optimistic-types=true option to an argument list if this
+ * is set to override the default false
+ *
+ * @args argument list
+ */
+ public static void addExplicitOptimisticTypes(final List<String> args) {
+ if (hasOptimisticOverride()) {
+ args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
+ }
+ }
+
private static boolean strictModeEnabled() {
return Boolean.getBoolean(TEST_JS_ENABLE_STRICT_MODE);
}
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestHelper.java b/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
index b48ed8b5..99e32802 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
@@ -36,10 +36,12 @@ import java.io.Reader;
/**
* Simple utilities to deal with build-dir, read/dump files etc.
*/
+@SuppressWarnings("javadoc")
public abstract class TestHelper {
public static final String TEST_ROOT = "test";
- public static final String BUILD_ROOT = "build/test";
+ public static final String BUILD_ROOT =
+ System.getProperty("build.dir", "build") + File.separator + "test";
public static final String TEST_PREFIX = TEST_ROOT + File.separator;
private TestHelper() {
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java b/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
index 7d7a7a30..51da19c9 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
@@ -38,7 +38,7 @@ import org.testng.ITestContext;
*/
public final class TestReorderInterceptor implements IMethodInterceptor {
@Override
- public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
+ public List<IMethodInstance> intercept(final List<IMethodInstance> methods, final ITestContext context) {
Collections.sort(methods, new Comparator<IMethodInstance>() {
@Override
public int compare(final IMethodInstance mi1, final IMethodInstance mi2) {
@@ -47,10 +47,9 @@ public final class TestReorderInterceptor implements IMethodInterceptor {
final Object o2 = mi2.getInstance();
if (o1 instanceof ITest && o2 instanceof ITest) {
return ((ITest)o1).getTestName().compareTo(((ITest)o2).getTestName());
- } else {
- // something else, don't care about the order
- return 0;
}
+ // something else, don't care about the order
+ return 0;
}
});
diff --git a/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java b/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java
index ed45139d..503d8f6e 100644
--- a/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java
+++ b/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java
@@ -28,6 +28,7 @@ package jdk.nashorn.internal.test.models;
import java.io.PrintWriter;
import java.io.StringWriter;
+@SuppressWarnings("javadoc")
public class InternalRunnable implements Runnable, RestrictedRunnable {
// This is a public field in a restricted class; scripts should not see it.
diff --git a/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java b/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java
index 05fd52c0..aa5bfb77 100644
--- a/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java
+++ b/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java
@@ -27,8 +27,8 @@ package jdk.nashorn.internal.test.models;
/**
* Acts as a restricted interface implemented by a restricted class.
- *
*/
+@SuppressWarnings("javadoc")
public interface RestrictedRunnable {
public void restrictedRun();
}
diff --git a/test/src/jdk/nashorn/test/models/ClassLoaderAware.java b/test/src/jdk/nashorn/test/models/ClassLoaderAware.java
new file mode 100644
index 00000000..491e9db2
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/ClassLoaderAware.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.test.models;
+
+@SuppressWarnings("javadoc")
+public interface ClassLoaderAware {
+ public ClassLoader getContextClassLoader();
+ public void checkMemberAccess(Class<?> clazz, int which);
+}
diff --git a/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java b/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java
index ba0d86d8..2d1906bf 100644
--- a/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java
+++ b/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java
@@ -25,7 +25,10 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class ClassWithFinalFinalizer {
+ @Override
protected final void finalize() {
+ //empty
}
}
diff --git a/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java b/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java
index 80393fbb..6a1f4d65 100644
--- a/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java
+++ b/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java
@@ -25,5 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class ClassWithInheritedFinalFinalizer extends ClassWithFinalFinalizer {
+ //empty
}
diff --git a/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java b/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
index 9a201575..1483a6e5 100644
--- a/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
+++ b/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
@@ -25,10 +25,11 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public abstract class ConstructorWithArgument {
private final String token;
- protected ConstructorWithArgument(String token) {
+ protected ConstructorWithArgument(final String token) {
this.token = token;
}
diff --git a/test/src/jdk/nashorn/test/models/DessertTopping.java b/test/src/jdk/nashorn/test/models/DessertTopping.java
index 591e032d..a4352499 100644
--- a/test/src/jdk/nashorn/test/models/DessertTopping.java
+++ b/test/src/jdk/nashorn/test/models/DessertTopping.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public interface DessertTopping {
public String pourOnDessert();
}
diff --git a/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java b/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
index 856029ad..f074ec3d 100644
--- a/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
+++ b/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
@@ -25,12 +25,13 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class DessertToppingFloorWaxDriver {
- public void decorateDessert(DessertTopping dt) {
+ public void decorateDessert(final DessertTopping dt) {
dt.pourOnDessert();
}
- public void waxFloor(FloorWax fw) {
+ public void waxFloor(final FloorWax fw) {
fw.shineUpTheFloor();
}
}
diff --git a/test/src/jdk/nashorn/test/models/FinalClass.java b/test/src/jdk/nashorn/test/models/FinalClass.java
index 8a3e8432..3b759dd2 100644
--- a/test/src/jdk/nashorn/test/models/FinalClass.java
+++ b/test/src/jdk/nashorn/test/models/FinalClass.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public final class FinalClass {
//empty
}
diff --git a/test/src/jdk/nashorn/test/models/FloorWax.java b/test/src/jdk/nashorn/test/models/FloorWax.java
index 44ac96e9..02439272 100644
--- a/test/src/jdk/nashorn/test/models/FloorWax.java
+++ b/test/src/jdk/nashorn/test/models/FloorWax.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public interface FloorWax {
public String shineUpTheFloor();
}
diff --git a/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
index 947896b3..52a74552 100644
--- a/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
+++ b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
@@ -24,13 +24,14 @@
*/
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class IntFloatOverloadSelection {
- public static String overloadedMethod(int i) {
+ public static String overloadedMethod(final int i) {
return "int";
}
- public static String overloadedMethod(float f) {
+ public static String overloadedMethod(final float f) {
return "float";
}
}
diff --git a/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java b/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java
index 24104c3d..3af717aa 100644
--- a/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java
+++ b/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java
@@ -30,8 +30,9 @@ import jdk.nashorn.internal.test.models.InternalRunnable;
/**
* Acts as a non-restricted superclass for a restricted class.
- *
*/
+
+@SuppressWarnings("javadoc")
public class InternalRunnableSuperclass {
public final int canSeeThisField = 19;
diff --git a/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java b/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
index 1b179758..d7f2a95f 100644
--- a/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
+++ b/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
@@ -26,22 +26,23 @@
package jdk.nashorn.test.models;
/**
- * Test class used by JDK-8011362.js.
+ * Test class used by JDK-8011362.js
*/
+@SuppressWarnings("javadoc")
public class Jdk8011362TestSubject {
// This is selected for overloaded("", null)
- public String overloaded(String a, String b) {
+ public String overloaded(final String a, final String b) {
return "overloaded(String, String)";
}
// This is selected for overloaded(0, null)
- public String overloaded(Double a, Double b) {
+ public String overloaded(final Double a, final Double b) {
return "overloaded(Double, Double)";
}
// This method is added to test that null will not match a primitive type, that is overloaded(0, null) will always
// select the (Double, Double) over (Double, double).
- public String overloaded(Double a, double b) {
+ public String overloaded(final Double a, final double b) {
return "overloaded(Double, double)";
}
}
diff --git a/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java b/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
index 2e7d9c6c..8d529442 100644
--- a/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
+++ b/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
@@ -25,32 +25,33 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class Nashorn401TestSubject {
- public String method2(int arg) {
+ public String method2(final int arg) {
return "int method 2";
}
- public String method2(double arg) {
+ public String method2(final double arg) {
return "double method 2";
}
- public String method2(String arg) {
+ public String method2(final String arg) {
return "string method 2";
}
- public String method3(double arg) {
+ public String method3(final double arg) {
return "double method 3: " + arg;
}
- public String method3(int arg) {
+ public String method3(final int arg) {
return "int method 3: " + arg;
}
- public String method4(Double arg) {
+ public String method4(final Double arg) {
return "double method 4: " + arg;
}
- public String method4(int arg) {
+ public String method4(final int arg) {
return "int method 4: " + arg;
}
diff --git a/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java b/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java
index f0ddb1aa..68ca4f88 100644
--- a/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java
+++ b/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class NoAccessibleConstructorClass {
NoAccessibleConstructorClass() { }
}
diff --git a/test/src/jdk/nashorn/test/models/NullProvider.java b/test/src/jdk/nashorn/test/models/NullProvider.java
new file mode 100644
index 00000000..128d1198
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/NullProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.test.models;
+
+
+public class NullProvider {
+ public static Integer getInteger() { return null; }
+ public static Long getLong() { return null; }
+ public static Double getDouble() { return null; }
+ public static Boolean getBoolean() { return null; }
+}
diff --git a/test/src/jdk/nashorn/test/models/OuterClass.java b/test/src/jdk/nashorn/test/models/OuterClass.java
index fc280f65..3d6f279a 100644
--- a/test/src/jdk/nashorn/test/models/OuterClass.java
+++ b/test/src/jdk/nashorn/test/models/OuterClass.java
@@ -25,21 +25,23 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class OuterClass {
private final String value;
- public OuterClass(String value) {
+ public OuterClass(final String value) {
this.value = value;
}
public static class InnerStaticClass {
public static class InnerInnerStaticClass {
+ //empty
}
private final String value;
- public InnerStaticClass(String value) {
+ public InnerStaticClass(final String value) {
this.value = value;
}
@@ -50,15 +52,15 @@ public class OuterClass {
}
public class InnerNonStaticClass {
- private final String value;
+ private final String val;
- public InnerNonStaticClass(String value) {
- this.value = value;
+ public InnerNonStaticClass(final String value) {
+ this.val = value;
}
@Override
public String toString() {
- return "InnerNonStaticClass[value=" + value + ", outer=" + OuterClass.this + "]";
+ return "InnerNonStaticClass[value=" + val + ", outer=" + OuterClass.this + "]";
}
}
diff --git a/test/src/jdk/nashorn/test/models/OverloadedSam.java b/test/src/jdk/nashorn/test/models/OverloadedSam.java
index 05736bca..b75f6b07 100644
--- a/test/src/jdk/nashorn/test/models/OverloadedSam.java
+++ b/test/src/jdk/nashorn/test/models/OverloadedSam.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public interface OverloadedSam {
public void sam(String s);
public void sam(String s1, String s2);
diff --git a/test/src/jdk/nashorn/test/models/OverrideObject.java b/test/src/jdk/nashorn/test/models/OverrideObject.java
index 5312ffbb..ed5a895e 100644
--- a/test/src/jdk/nashorn/test/models/OverrideObject.java
+++ b/test/src/jdk/nashorn/test/models/OverrideObject.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class OverrideObject {
@Override
public int hashCode() {
@@ -37,7 +38,7 @@ public class OverrideObject {
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
// TODO: add a FindBugs annotation to ignore EQ_ALWAYS_FALSE here. This is just a test.
return false;
}
diff --git a/test/src/jdk/nashorn/test/models/PropertyBind.java b/test/src/jdk/nashorn/test/models/PropertyBind.java
index c1af3023..09e85309 100644
--- a/test/src/jdk/nashorn/test/models/PropertyBind.java
+++ b/test/src/jdk/nashorn/test/models/PropertyBind.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public class PropertyBind {
public static int publicStaticInt;
public static final int publicStaticFinalInt = 2112;
@@ -37,14 +38,14 @@ public class PropertyBind {
public final int publicFinalInt = 42;
private int readWrite;
- private int readOnly = 123;
+ private final int readOnly = 123;
private int writeOnly;
public int getReadWrite() {
return readWrite;
}
- public void setReadWrite(int readWrite) {
+ public void setReadWrite(final int readWrite) {
this.readWrite = readWrite;
}
@@ -52,7 +53,7 @@ public class PropertyBind {
return readOnly;
}
- public void setWriteOnly(int writeOnly) {
+ public void setWriteOnly(final int writeOnly) {
this.writeOnly = writeOnly;
}
@@ -64,7 +65,7 @@ public class PropertyBind {
return staticReadWrite;
}
- public static void setStaticReadWrite(int staticReadWrite) {
+ public static void setStaticReadWrite(final int staticReadWrite) {
PropertyBind.staticReadWrite = staticReadWrite;
}
@@ -72,7 +73,7 @@ public class PropertyBind {
return staticReadOnly;
}
- public static void setStaticWriteOnly(int staticWriteOnly) {
+ public static void setStaticWriteOnly(final int staticWriteOnly) {
PropertyBind.staticWriteOnly = staticWriteOnly;
}
diff --git a/test/src/jdk/nashorn/test/models/SourceHelper.java b/test/src/jdk/nashorn/test/models/SourceHelper.java
index 7e90f304..d0525827 100644
--- a/test/src/jdk/nashorn/test/models/SourceHelper.java
+++ b/test/src/jdk/nashorn/test/models/SourceHelper.java
@@ -34,6 +34,7 @@ import jdk.nashorn.internal.runtime.Source;
/**
* Helper class to facilitate script access of nashorn Source class.
*/
+@SuppressWarnings("javadoc")
public final class SourceHelper {
private SourceHelper() {}
diff --git a/test/src/jdk/nashorn/test/models/StringArgs.java b/test/src/jdk/nashorn/test/models/StringArgs.java
index 1fdcd5de..d80480f5 100644
--- a/test/src/jdk/nashorn/test/models/StringArgs.java
+++ b/test/src/jdk/nashorn/test/models/StringArgs.java
@@ -27,10 +27,11 @@ package jdk.nashorn.test.models;
import java.util.List;
+@SuppressWarnings("javadoc")
public class StringArgs {
- public static void checkString(List<?> list) {
- for (Object s : list) {
+ public static void checkString(final List<?> list) {
+ for (final Object s : list) {
if (!(s instanceof String)) {
throw new AssertionError("Not a String: " + s);
}
diff --git a/test/src/jdk/nashorn/test/models/Toothpaste.java b/test/src/jdk/nashorn/test/models/Toothpaste.java
index 7eae95f3..747de89c 100644
--- a/test/src/jdk/nashorn/test/models/Toothpaste.java
+++ b/test/src/jdk/nashorn/test/models/Toothpaste.java
@@ -25,6 +25,7 @@
package jdk.nashorn.test.models;
+@SuppressWarnings("javadoc")
public abstract class Toothpaste {
public void applyToBrush() {
applyToBrushImpl();
diff --git a/test/src/jdk/nashorn/test/models/VarArgConstructor.java b/test/src/jdk/nashorn/test/models/VarArgConstructor.java
index 5f5da30e..6c31627f 100644
--- a/test/src/jdk/nashorn/test/models/VarArgConstructor.java
+++ b/test/src/jdk/nashorn/test/models/VarArgConstructor.java
@@ -27,14 +27,15 @@ package jdk.nashorn.test.models;
import java.util.List;
+@SuppressWarnings("javadoc")
public class VarArgConstructor {
private final String indicator;
- public VarArgConstructor(int x, boolean y, List<String> z) {
+ public VarArgConstructor(final int x, final boolean y, final List<String> z) {
indicator = "non-vararg";
}
- public VarArgConstructor(int x, boolean y, String... z) {
+ public VarArgConstructor(final int x, final boolean y, final String... z) {
indicator = "vararg";
}
diff --git a/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java b/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java
new file mode 100644
index 00000000..8a971f3d
--- /dev/null
+++ b/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.test.tools;
+
+import jdk.nashorn.internal.runtime.Undefined;
+
+@SuppressWarnings("javadoc")
+public class StaticTypeInspector {
+
+ public static String inspect(final boolean x, final String w) {
+ return w + ": boolean";
+ }
+
+ public static String inspect(final int x, final String w) {
+ return w + ": int";
+ }
+
+ public static String inspect(final long x, final String w) {
+ return w + ": long";
+ }
+
+ public static String inspect(final double x, final String w) {
+ return w + ": double";
+ }
+
+ public static String inspect(final Undefined x, final String w) {
+ return w + ": undefined";
+ }
+
+ public static String inspect(final Object x, final String w) {
+ return w + ": object";
+ }
+}